Restructure the Spring Boot for Apache Geode project to mirror Spring Boot's project structure.
Resolves gh-60.
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.cache;
|
||||
|
||||
import org.apache.geode.cache.CacheListener;
|
||||
import org.apache.geode.cache.EntryEvent;
|
||||
import org.apache.geode.cache.RegionEvent;
|
||||
import org.apache.geode.cache.util.CacheListenerAdapter;
|
||||
|
||||
/**
|
||||
* An {@link Class abstract base class} implementing the Apache Geode {@link CacheListener} interface
|
||||
* by extending the {@link CacheListenerAdapter} base class, which processes all {@link EntryEvent EntryEvents}
|
||||
* and {@link RegionEvent RegionEvents} using the same logic.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.CacheListener
|
||||
* @see org.apache.geode.cache.EntryEvent
|
||||
* @see org.apache.geode.cache.RegionEvent
|
||||
* @see org.apache.geode.cache.util.CacheListenerAdapter
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public abstract class AbstractCommonEventProcessingCacheListener<K, V> extends CacheListenerAdapter<K, V> {
|
||||
|
||||
@Override
|
||||
public void afterCreate(EntryEvent<K, V> event) {
|
||||
processEntryEvent(event, EntryEventType.CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterDestroy(EntryEvent<K, V> event) {
|
||||
processEntryEvent(event, EntryEventType.DESTROY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterInvalidate(EntryEvent<K, V> event) {
|
||||
processEntryEvent(event, EntryEventType.INVALIDATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterUpdate(EntryEvent<K, V> event) {
|
||||
processEntryEvent(event, EntryEventType.UPDATE);
|
||||
}
|
||||
|
||||
protected void processEntryEvent(EntryEvent<K, V> event, EntryEventType eventType) { }
|
||||
|
||||
@Override
|
||||
public void afterRegionClear(RegionEvent<K, V> event) {
|
||||
processRegionEvent(event, RegionEventType.CLEAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRegionCreate(RegionEvent<K, V> event) {
|
||||
processRegionEvent(event, RegionEventType.CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRegionDestroy(RegionEvent<K, V> event) {
|
||||
processRegionEvent(event, RegionEventType.DESTROY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRegionInvalidate(RegionEvent<K, V> event) {
|
||||
processRegionEvent(event, RegionEventType.INVALIDATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRegionLive(RegionEvent<K, V> event) {
|
||||
processRegionEvent(event, RegionEventType.LIVE);
|
||||
}
|
||||
|
||||
protected void processRegionEvent(RegionEvent<K, V> event, RegionEventType eventType) { }
|
||||
|
||||
public enum EntryEventType {
|
||||
|
||||
CREATE,
|
||||
DESTROY,
|
||||
INVALIDATE,
|
||||
UPDATE;
|
||||
|
||||
}
|
||||
|
||||
public enum RegionEventType {
|
||||
|
||||
CLEAR,
|
||||
CREATE,
|
||||
DESTROY,
|
||||
INVALIDATE,
|
||||
LIVE;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.cache;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.CacheFactory;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.RegionService;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.ClientCacheFactory;
|
||||
|
||||
import org.springframework.geode.util.CacheUtils;
|
||||
|
||||
/**
|
||||
* The {@link SimpleCacheResolver} abstract class contains utility functions for resolving Apache Geode
|
||||
* {@link GemFireCache} instances, such as a {@link ClientCache} or a {@literal peer} {@link Cache}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.CacheFactory
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.RegionService
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.client.ClientCacheFactory
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class SimpleCacheResolver {
|
||||
|
||||
private static final AtomicReference<SimpleCacheResolver> instance = new AtomicReference<>(null);
|
||||
|
||||
/**
|
||||
* Lazily constructs and gets an instance to the {@link SimpleCacheResolver}, as needed.
|
||||
*
|
||||
* @return an instance of the {@link SimpleCacheResolver}.
|
||||
* @see #newSimpleCacheResolver()
|
||||
*/
|
||||
public static SimpleCacheResolver getInstance() {
|
||||
|
||||
return instance.updateAndGet(cacheResolver -> cacheResolver != null
|
||||
? cacheResolver
|
||||
: newSimpleCacheResolver());
|
||||
}
|
||||
|
||||
// TODO Consider resolving the SimpleCacheResolver instance using Java's ServiceProvider API.
|
||||
private static SimpleCacheResolver newSimpleCacheResolver() {
|
||||
return new SimpleCacheResolver() { };
|
||||
}
|
||||
|
||||
/**
|
||||
* The 1st {@code resolve():Optional<? extends GemFireCache>} method signature avoids the cast
|
||||
* and the @SuppressWarnings("unchecked") annotation, but puts the burden on the caller.
|
||||
* The 2nd {@code resolve():Optional<T extends GemFireCache>} method signature requires a cast
|
||||
* and the @SuppressWarnings("unchecked") annotation, but avoids putting the burden on the caller.
|
||||
*/
|
||||
private static void testCallResolve() {
|
||||
Optional<ClientCache> clientCache = getInstance().resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* The resolution algorithm first tries to resolve an {@link Optional} {@link ClientCache} instance
|
||||
* then a {@literal peer} {@link Cache} instance if a {@link ClientCache} is not present.
|
||||
*
|
||||
* If neither a {@link ClientCache} or {@literal peer} {@link Cache} is available, then {@link Optional#empty()}
|
||||
* is returned. No {@link Throwable Exception} is thrown.
|
||||
*
|
||||
* @param <T> {@link Class subclass} of {@link GemFireCache}.
|
||||
* @return a {@link ClientCache} or then a {@literal peer} {@link Cache} instance if present.
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see java.util.Optional
|
||||
* @see #resolveClientCache()
|
||||
* @see #resolvePeerCache()
|
||||
*/
|
||||
//public static Optional<? extends GemFireCache> resolve() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends GemFireCache> Optional<T> resolve() {
|
||||
|
||||
Optional<ClientCache> clientCache = resolveClientCache();
|
||||
|
||||
return (Optional<T>) (clientCache.isPresent() ? clientCache : resolvePeerCache());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to resolve an {@link Optional} {@link ClientCache} instance.
|
||||
*
|
||||
* @return an {@link Optional} {@link ClientCache} instance.
|
||||
* @see org.springframework.geode.util.CacheUtils#isClientCache(RegionService)
|
||||
* @see org.apache.geode.cache.client.ClientCacheFactory#getAnyInstance()
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
public Optional<ClientCache> resolveClientCache() {
|
||||
|
||||
try {
|
||||
return Optional.ofNullable(ClientCacheFactory.getAnyInstance())
|
||||
.filter(CacheUtils::isClientCache);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to resolve an {@link Optional} {@link Cache} instance.
|
||||
*
|
||||
* @return an {@link Optional} {@link Cache} instance.
|
||||
* @see org.springframework.geode.util.CacheUtils#isPeerCache(RegionService)
|
||||
* @see org.apache.geode.cache.CacheFactory#getAnyInstance()
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
public Optional<Cache> resolvePeerCache() {
|
||||
|
||||
try {
|
||||
return Optional.ofNullable(CacheFactory.getAnyInstance())
|
||||
.filter(CacheUtils::isPeerCache);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requires an instance of either a {@link ClientCache} or a {@literal peer} {@link Cache}.
|
||||
*
|
||||
* @param <T> {@link Class subclass} of {@link GemFireCache} to resolve.
|
||||
* @return an instance of either a {@link ClientCache} or a {@literal peer} {@link Cache}.
|
||||
* @throws IllegalStateException if a cache instance cannot be resolved.
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see #resolve()
|
||||
*/
|
||||
public <T extends GemFireCache> T require() {
|
||||
return this.<T>resolve()
|
||||
.orElseThrow(() -> new IllegalStateException("GemFireCache not found"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.distributed.event;
|
||||
|
||||
import java.util.EventObject;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.distributed.DistributedMember;
|
||||
import org.apache.geode.distributed.DistributedSystem;
|
||||
import org.apache.geode.distributed.internal.DistributionManager;
|
||||
|
||||
/**
|
||||
* {@link EventObject} implementation indicating a membership event in the {@link DistributedSystem}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @param <T> specific {@link Class type} of {@link MembershipEvent}.
|
||||
* @see java.util.EventObject
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.apache.geode.distributed.internal.DistributionManager
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class MembershipEvent<T extends MembershipEvent<T>> extends EventObject {
|
||||
|
||||
private DistributedMember distributedMember;
|
||||
|
||||
/**
|
||||
* Asserts that the given {@link Object target} is not {@literal null}.
|
||||
*
|
||||
* @param <T> {@link Class type} of the {@link Object target}.
|
||||
* @param target {@link Object} to evaluate.
|
||||
* @param message {@link String} containing the message for the {@link IllegalArgumentException}.
|
||||
* @param arguments array of {@link Object arguments} to populate the placeholders in the {@link String message}.
|
||||
* @return the {@link Object target}.
|
||||
* @throws IllegalArgumentException if {@link Object target} is {@literal null}.
|
||||
*/
|
||||
protected static <T> T assertNotNull(T target, String message, Object... arguments) {
|
||||
|
||||
if (target == null) {
|
||||
throw new IllegalArgumentException(String.format(message, arguments));
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of {@link MembershipEvent} initialized with the given {@link DistributionManager}.
|
||||
*
|
||||
* @param distributionManager {@link DistributionManager} used to acquire the {@link Cache}, which is used
|
||||
* as the {@literal source} of this event.
|
||||
* @throws IllegalArgumentException if {@link DistributionManager} is {@literal null}.
|
||||
* @see org.apache.geode.distributed.internal.DistributionManager
|
||||
*/
|
||||
public MembershipEvent(DistributionManager distributionManager) {
|
||||
super(assertNotNull(distributionManager, "DistributionManager must not be null"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} reference to the {@literal peer} {@link Cache}.
|
||||
*
|
||||
* @return an {@link Optional} reference to the {@literal peer} {@link Cache}.
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see #getDistributionManager()
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
public Optional<Cache> getCache() {
|
||||
return Optional.ofNullable(getDistributionManager().getCache());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} reference to the {@link DistributedMember} that is the subject
|
||||
* of this {@link MembershipEvent}.
|
||||
*
|
||||
* @return an {@link Optional} reference to the {@link DistributedMember} that is the subject of this event.
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see #getDistributionManager()
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
public Optional<DistributedMember> getDistributedMember() {
|
||||
return Optional.ofNullable(this.distributedMember);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} reference to the {@link DistributedSystem} (cluster) to which the {@literal peer}
|
||||
* {@link Cache} is connected.
|
||||
*
|
||||
* @return an {@link Optional} reference to the {@link DistributedSystem}.
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see #getDistributionManager()
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
public Optional<DistributedSystem> getDistributedSystem() {
|
||||
return Optional.ofNullable(getDistributionManager().getSystem());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the configured {@link DistributionManager} which is use as the {@link #getSource() source}
|
||||
* of this event.
|
||||
*
|
||||
* @return a reference to the {@link DistributionManager}.
|
||||
* @see org.apache.geode.distributed.internal.DistributionManager
|
||||
*/
|
||||
public DistributionManager getDistributionManager() {
|
||||
return (DistributionManager) getSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Type} of this {@link MembershipEvent}, such as {@link Type#MEMBER_JOINED}.
|
||||
*
|
||||
* @return the {@link MembershipEvent.Type}.
|
||||
*/
|
||||
public Type getType() {
|
||||
return Type.UNQUALIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe builder method used to configure the {@link DistributedMember member} that is the subject
|
||||
* of this event.
|
||||
*
|
||||
* @param distributedMember {@link DistributedMember} that is the subject of this event.
|
||||
* @return this {@link MembershipEvent}.
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see #getDistributedMember()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withMember(DistributedMember distributedMember) {
|
||||
|
||||
this.distributedMember = distributedMember;
|
||||
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* An {@link Enum enumeration} of different type of {@link MembershipEvent MembershipEvents}.
|
||||
*/
|
||||
public enum Type {
|
||||
|
||||
MEMBER_DEPARTED,
|
||||
MEMBER_JOINED,
|
||||
MEMBER_SUSPECT,
|
||||
QUORUM_LOST,
|
||||
UNQUALIFIED;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.distributed.event;
|
||||
|
||||
import java.util.EventListener;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.distributed.internal.DistributionManager;
|
||||
import org.apache.geode.distributed.internal.InternalDistributedSystem;
|
||||
import org.apache.geode.distributed.internal.MembershipListener;
|
||||
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
|
||||
|
||||
import org.springframework.geode.distributed.event.support.MemberDepartedEvent;
|
||||
import org.springframework.geode.distributed.event.support.MemberJoinedEvent;
|
||||
import org.springframework.geode.distributed.event.support.MemberSuspectEvent;
|
||||
import org.springframework.geode.distributed.event.support.QuorumLostEvent;
|
||||
|
||||
/**
|
||||
* An abstract {@link MembershipListener} implementation using the
|
||||
* <a href="https://en.wikipedia.org/wiki/Adapter_pattern">Adapter Software Design Pattern</a>
|
||||
* to delegate membership event callbacks to event handlers for those membership events.
|
||||
*
|
||||
* @author John Blum
|
||||
* @param <T> specific {@link Class sub-type} of this {@link MembershipListenerAdapter}.
|
||||
* @see java.util.EventListener
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.distributed.internal.DistributionManager
|
||||
* @see org.apache.geode.distributed.internal.InternalDistributedSystem
|
||||
* @see org.apache.geode.distributed.internal.MembershipListener
|
||||
* @see org.apache.geode.distributed.internal.membership.InternalDistributedMember
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class MembershipListenerAdapter<T extends MembershipListenerAdapter<T>>
|
||||
implements EventListener, MembershipListener {
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public final void memberDeparted(DistributionManager manager, InternalDistributedMember member, boolean crashed) {
|
||||
|
||||
MemberDepartedEvent event = new MemberDepartedEvent(manager)
|
||||
.withMember(member)
|
||||
.crashed(crashed);
|
||||
|
||||
handleMemberDeparted(event);
|
||||
}
|
||||
|
||||
public void handleMemberDeparted(MemberDepartedEvent event) { }
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public final void memberJoined(DistributionManager manager, InternalDistributedMember member) {
|
||||
|
||||
MemberJoinedEvent event = new MemberJoinedEvent(manager)
|
||||
.withMember(member);
|
||||
|
||||
handleMemberJoined(event);
|
||||
}
|
||||
|
||||
public void handleMemberJoined(MemberJoinedEvent event) { }
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public final void memberSuspect(DistributionManager manager, InternalDistributedMember member,
|
||||
InternalDistributedMember suspectMember, String reason) {
|
||||
|
||||
MemberSuspectEvent event = new MemberSuspectEvent(manager)
|
||||
.withMember(member)
|
||||
.withReason(reason)
|
||||
.withSuspect(suspectMember);
|
||||
|
||||
handleMemberSuspect(event);
|
||||
}
|
||||
|
||||
public void handleMemberSuspect(MemberSuspectEvent event) { }
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public final void quorumLost(DistributionManager manager, Set<InternalDistributedMember> failedMembers,
|
||||
List<InternalDistributedMember> remainingMembers) {
|
||||
|
||||
QuorumLostEvent event = new QuorumLostEvent(manager)
|
||||
.withFailedMembers(failedMembers)
|
||||
.withRemainingMembers(remainingMembers);
|
||||
|
||||
handleQuorumLost(event);
|
||||
}
|
||||
|
||||
public void handleQuorumLost(QuorumLostEvent event) { }
|
||||
|
||||
/**
|
||||
* Registers this {@link MembershipListener} with the given {@literal peer} {@link Cache}.
|
||||
*
|
||||
* @param peerCache {@literal peer} {@link Cache} on which to register this {@link MembershipListener}.
|
||||
* @return this {@link MembershipListenerAdapter}.
|
||||
* @see org.apache.geode.cache.Cache
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T register(Cache peerCache) {
|
||||
|
||||
Optional.ofNullable(peerCache)
|
||||
.map(Cache::getDistributedSystem)
|
||||
.filter(InternalDistributedSystem.class::isInstance)
|
||||
.map(InternalDistributedSystem.class::cast)
|
||||
.map(InternalDistributedSystem::getDistributionManager)
|
||||
.ifPresent(distributionManager -> distributionManager
|
||||
.addMembershipListener(this));
|
||||
|
||||
return (T) this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.distributed.event.support;
|
||||
|
||||
import org.apache.geode.distributed.DistributedMember;
|
||||
import org.apache.geode.distributed.DistributedSystem;
|
||||
import org.apache.geode.distributed.internal.DistributionManager;
|
||||
|
||||
import org.springframework.geode.distributed.event.MembershipEvent;
|
||||
|
||||
/**
|
||||
* {@link MembershipEvent} fired when a {@link DistributedMember} departs from the {@link DistributedSystem}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.springframework.geode.distributed.event.MembershipEvent
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class MemberDepartedEvent extends MembershipEvent<MemberDepartedEvent> {
|
||||
|
||||
private boolean crashed = false;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of {@link MemberDepartedEvent} initialized with the given {@link DistributionManager}.
|
||||
*
|
||||
* @param distributionManager {@link DistributionManager} used as the {@link #getSource() source} of this event;
|
||||
* must not be {@literal null}.
|
||||
* @throws IllegalArgumentException if {@link DistributionManager} is {@literal null}.
|
||||
* @see org.apache.geode.distributed.internal.DistributionManager
|
||||
*/
|
||||
public MemberDepartedEvent(DistributionManager distributionManager) {
|
||||
super(distributionManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the peer member crashed when it departed from the {@link DistributedSystem} (cluster).
|
||||
*
|
||||
* @return a boolean value indicating whether the peer member crashed when it departed
|
||||
* from the {@link DistributedSystem} (cluster).
|
||||
*/
|
||||
public boolean isCrashed() {
|
||||
return this.crashed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder method used to configure the {@link #isCrashed()} property indicating whether the peer member crashed
|
||||
* when it departed from the {@link DistributedSystem}.
|
||||
*
|
||||
* @param crashed boolean value indicating whether the peer member crashed.
|
||||
* @return this {@link MemberDepartedEvent}.
|
||||
* @see #isCrashed()
|
||||
*/
|
||||
public MemberDepartedEvent crashed(boolean crashed) {
|
||||
|
||||
this.crashed = crashed;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public final Type getType() {
|
||||
return Type.MEMBER_DEPARTED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.distributed.event.support;
|
||||
|
||||
import org.apache.geode.distributed.DistributedMember;
|
||||
import org.apache.geode.distributed.DistributedSystem;
|
||||
import org.apache.geode.distributed.internal.DistributionManager;
|
||||
|
||||
import org.springframework.geode.distributed.event.MembershipEvent;
|
||||
|
||||
/**
|
||||
* {@link MembershipEvent} fired when a {@link DistributedMember} joins the {@link DistributedSystem}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.springframework.geode.distributed.event.MembershipEvent
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class MemberJoinedEvent extends MembershipEvent<MemberJoinedEvent> {
|
||||
|
||||
/**
|
||||
* Constructs a new instance of {@link MemberJoinedEvent} initialized with the given {@link DistributionManager}.
|
||||
*
|
||||
* @param distributionManager {@link DistributionManager} used as the {@link #getSource() source} of this event;
|
||||
* must not be {@literal null}.
|
||||
* @throws IllegalArgumentException if {@link DistributionManager} is {@literal null}.
|
||||
* @see org.apache.geode.distributed.internal.DistributionManager
|
||||
*/
|
||||
public MemberJoinedEvent(DistributionManager distributionManager) {
|
||||
super(distributionManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.MEMBER_JOINED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.distributed.event.support;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.distributed.DistributedMember;
|
||||
import org.apache.geode.distributed.DistributedSystem;
|
||||
import org.apache.geode.distributed.internal.DistributionManager;
|
||||
|
||||
import org.springframework.geode.distributed.event.MembershipEvent;
|
||||
|
||||
/**
|
||||
* {@link MembershipEvent} fired when a {@link DistributedMember} of the {@link DistributedSystem} is suspected
|
||||
* of being unresponsive to other {@link DistributedMember peer members} in the cluster.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.springframework.geode.distributed.event.MembershipEvent
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class MemberSuspectEvent extends MembershipEvent<MemberSuspectEvent> {
|
||||
|
||||
private DistributedMember suspectMember;
|
||||
|
||||
private String reason;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of {@link MemberSuspectEvent} initialized with the given {@link DistributionManager}.
|
||||
*
|
||||
* @param distributionManager {@link DistributionManager} used as the {@link #getSource() source} of this event;
|
||||
* must not be {@literal null}.
|
||||
* @throws IllegalArgumentException if {@link DistributionManager} is {@literal null}.
|
||||
* @see org.apache.geode.distributed.internal.DistributionManager
|
||||
*/
|
||||
public MemberSuspectEvent(DistributionManager distributionManager) {
|
||||
super(distributionManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} {@link String reason} describing the suspicion of the peer member.
|
||||
*
|
||||
* @return an {@link Optional} {@link String reason} describing the suspicion of the peer member.
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
public Optional<String> getReason() {
|
||||
return Optional.ofNullable(this.reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} {@link DistributedMember} identified as the suspect in the {@link MembershipEvent}.
|
||||
*
|
||||
* @return an {@link Optional} {@link DistributedMember} identified as the suspect in the {@link MembershipEvent}.
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
public Optional<DistributedMember> getSuspectMember() {
|
||||
return Optional.ofNullable(this.suspectMember);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder method used to configure the {@link String reason} describing the suspicion of
|
||||
* the {@link DistributedMember suspect member}.
|
||||
*
|
||||
* @param reason {@link String} describing the suspicion of the {@link DistributedMember peer member};
|
||||
* may be {@literal null}.
|
||||
* @return this {@link MemberSuspectEvent}.
|
||||
* @see #getReason()
|
||||
*/
|
||||
public MemberSuspectEvent withReason(String reason) {
|
||||
|
||||
this.reason = reason;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder method used to configure the {@link DistributedMember peer member} that is the subject of the suspicion
|
||||
* {@link MembershipEvent}.
|
||||
*
|
||||
* @param suspectMember {@link DistributedMember peer member} that is being suspected; may be {@literal null}.
|
||||
* @return this {@link MemberSuspectEvent}.
|
||||
* @see #getSuspectMember()
|
||||
*/
|
||||
public MemberSuspectEvent withSuspect(DistributedMember suspectMember) {
|
||||
|
||||
this.suspectMember = suspectMember;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public final Type getType() {
|
||||
return Type.MEMBER_SUSPECT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.distributed.event.support;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.geode.distributed.DistributedMember;
|
||||
import org.apache.geode.distributed.DistributedSystem;
|
||||
import org.apache.geode.distributed.internal.DistributionManager;
|
||||
|
||||
import org.springframework.geode.distributed.event.MembershipEvent;
|
||||
|
||||
/**
|
||||
* {@link QuorumLostEvent} is fired for the losing side of the {@link DistributedSystem} when
|
||||
* a network partition occurs.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.springframework.geode.distributed.event.MembershipEvent
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class QuorumLostEvent extends MembershipEvent<QuorumLostEvent> {
|
||||
|
||||
private Iterable<? extends DistributedMember> remainingMembers = Collections.emptyList();
|
||||
|
||||
private Iterable<? extends DistributedMember> failedMembers = Collections.emptySet();
|
||||
|
||||
/**
|
||||
* Constructs a new instance of {@link QuorumLostEvent} initialized with the given {@link DistributionManager}.
|
||||
*
|
||||
* @param distributionManager {@link DistributionManager} used as the {@link #getSource() source} of this event;
|
||||
* must not be {@literal null}.
|
||||
* @throws IllegalArgumentException if {@link DistributionManager} is {@literal null}.
|
||||
* @see org.apache.geode.distributed.internal.DistributionManager
|
||||
*/
|
||||
public QuorumLostEvent(DistributionManager distributionManager) {
|
||||
super(distributionManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configured {@link Iterable} of failed {@link DistributedMember peer members}
|
||||
* in the {@link DistributedSystem} that are on the losing side of a network partition.
|
||||
*
|
||||
* @return an {@link Iterable} of failed {@link DistributedMember peer members}; never {@literal null}.
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see #getRemainingMembers()
|
||||
* @see java.lang.Iterable
|
||||
*/
|
||||
public Iterable<? extends DistributedMember> getFailedMembers() {
|
||||
return this.failedMembers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configured {@link Iterable} of remaining {@link DistributedMember peer members}
|
||||
* in the {@link DistributedSystem} that are on the winning side of a network partition.
|
||||
*
|
||||
* @return an {@link Iterable} of remaining {@link DistributedMember peer members}; never {@literal null}.
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see #getFailedMembers()
|
||||
* @see java.lang.Iterable
|
||||
*/
|
||||
public Iterable<? extends DistributedMember> getRemainingMembers() {
|
||||
return this.remainingMembers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe builder method used to configure an array of failing {@link DistributedMember peer members}
|
||||
* in the {@link DistributedSystem} on the losing side of a network partition.
|
||||
*
|
||||
* @param failedMembers array of failed {@link DistributedMember peer members}; may be {@literal null}.
|
||||
* @return this {@link QuorumLostEvent}.
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see #withFailedMembers(Iterable)
|
||||
* @see #getFailedMembers()
|
||||
*/
|
||||
public QuorumLostEvent withFailedMembers(DistributedMember... failedMembers) {
|
||||
|
||||
return withFailedMembers(failedMembers != null
|
||||
? Arrays.asList(failedMembers)
|
||||
: Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe builder method used to configure an {@link Iterable} of failing {@link DistributedMember peer members}
|
||||
* in the {@link DistributedSystem} on the losing side of a network partition.
|
||||
*
|
||||
* @param failedMembers {@link Iterable} of failed {@link DistributedMember peer members}; may be {@literal null}.
|
||||
* @return this {@link QuorumLostEvent}.
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see #getFailedMembers()
|
||||
* @see java.lang.Iterable
|
||||
*/
|
||||
public QuorumLostEvent withFailedMembers(Iterable<? extends DistributedMember> failedMembers) {
|
||||
|
||||
this.failedMembers = failedMembers != null
|
||||
? failedMembers
|
||||
: Collections.emptySet();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe builder method used to configure an array of remaining {@link DistributedMember peer members}
|
||||
* in the {@link DistributedSystem} on the winning side of a network partition.
|
||||
*
|
||||
* @param remainingMembers array of remaining {@link DistributedMember peer members}; may be {@literal null}.
|
||||
* @return this {@link QuorumLostEvent}.
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see #withRemainingMembers(Iterable)
|
||||
* @see #getRemainingMembers()
|
||||
*/
|
||||
public QuorumLostEvent withRemainingMembers(DistributedMember... remainingMembers) {
|
||||
|
||||
return withRemainingMembers(remainingMembers != null
|
||||
? Arrays.asList(remainingMembers)
|
||||
: Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe builder method used to configure an {@link Iterable} of remaining {@link DistributedMember peer members}
|
||||
* in the {@link DistributedSystem} on the winning side of a network partition.
|
||||
*
|
||||
* @param remainingMembers {@link Iterable} of remaining {@link DistributedMember peer members};
|
||||
* may be {@literal null}.
|
||||
* @return this {@link QuorumLostEvent}.
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see #getRemainingMembers()
|
||||
* @see java.lang.Iterable
|
||||
*/
|
||||
public QuorumLostEvent withRemainingMembers(Iterable<? extends DistributedMember> remainingMembers) {
|
||||
|
||||
this.remainingMembers = remainingMembers != null
|
||||
? remainingMembers
|
||||
: Collections.emptyList();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public final Type getType() {
|
||||
return Type.QUORUM_LOST;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.pdx;
|
||||
|
||||
import org.apache.geode.pdx.PdxInstance;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown to indicate that a PDX field of a {@link PdxInstance} is not writable.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.RuntimeException
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class PdxFieldNotWritableException extends RuntimeException {
|
||||
|
||||
public PdxFieldNotWritableException() { }
|
||||
|
||||
public PdxFieldNotWritableException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public PdxFieldNotWritableException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public PdxFieldNotWritableException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.pdx;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.RegionService;
|
||||
import org.apache.geode.pdx.PdxInstance;
|
||||
import org.apache.geode.pdx.PdxInstanceFactory;
|
||||
|
||||
import org.springframework.geode.cache.SimpleCacheResolver;
|
||||
|
||||
/**
|
||||
* The {@link PdxInstanceBuilder} class is a <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder</a>
|
||||
* used to construct and initialize a {@link PdxInstance} from different sources.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.RegionService
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see org.apache.geode.pdx.PdxInstanceFactory
|
||||
* @see <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder Software Design Pattern</a>
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class PdxInstanceBuilder {
|
||||
|
||||
/**
|
||||
* Factory method used to construct a new instance of the {@link PdxInstanceBuilder} class.
|
||||
*
|
||||
* This factory method tries to resolve the {@link GemFireCache} instance for the caller
|
||||
* by using {@link SimpleCacheResolver}.
|
||||
*
|
||||
* Alternatively, callers may provider their own {@link GemFireCache} instance by calling
|
||||
* {@link #create(RegionService)}.
|
||||
*
|
||||
* @return a new instance of the {@link PdxInstanceBuilder}.
|
||||
* @throws IllegalArgumentException if a {@link GemFireCache} instance is not present.
|
||||
* @see #create(RegionService)
|
||||
*/
|
||||
public static PdxInstanceBuilder create() {
|
||||
return create(SimpleCacheResolver.getInstance().require());
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method use to construct a new instance of the {@link PdxInstanceBuilder} class initialized with
|
||||
* the given, required {@link RegionService} used by the Builder to performs its functions.
|
||||
*
|
||||
* @param regionService {@link RegionService} instance used by the {@link PdxInstanceBuilder} to perform
|
||||
* its functions;
|
||||
* must not be {@literal null}.
|
||||
* @return an new instance of the {@link PdxInstanceBuilder}.
|
||||
* @throws IllegalArgumentException if {@link GemFireCache} is {@literal null}.
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see #PdxInstanceBuilder(RegionService)
|
||||
*/
|
||||
public static PdxInstanceBuilder create(RegionService regionService) {
|
||||
return new PdxInstanceBuilder(regionService);
|
||||
}
|
||||
|
||||
private static void assertNotNull(Object target, String message, Object... arguments) {
|
||||
|
||||
if (target == null) {
|
||||
throw new IllegalArgumentException(String.format(message, arguments));
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> List<T> nullSafeList(List<T> list) {
|
||||
return list != null ? list : Collections.emptyList();
|
||||
}
|
||||
|
||||
private final RegionService regionService;
|
||||
|
||||
private PdxInstanceFactory pdxFactory;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of {@link PdxInstanceBuilder} initialized with the required {@link RegionService}.
|
||||
*
|
||||
* @param regionService {@link RegionService} instance used to perform the functions of the PDX Builder.
|
||||
* @throws IllegalArgumentException if {@link RegionService} is {@literal null}.
|
||||
* @see org.apache.geode.cache.RegionService
|
||||
*/
|
||||
protected PdxInstanceBuilder(RegionService regionService) {
|
||||
|
||||
assertNotNull(regionService, "RegionService must not be null");
|
||||
|
||||
this.regionService = regionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the configured {@link RegionService} used to perform the operations of this PDX Builder.
|
||||
*
|
||||
* @return a reference to the configured {@link RegionService}; never {@literal null}.
|
||||
*/
|
||||
protected RegionService getRegionService() {
|
||||
return this.regionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the contents of the existing {@link PdxInstance} to a new {@link PdxInstance} built with this Builder.
|
||||
*
|
||||
* @param pdxInstance {@link PdxInstance} to copy.
|
||||
* @return an instance of the {@link PdxInstanceFactory} used to {@link PdxInstanceFactory#create() create}
|
||||
* the {@link PdxInstance}.
|
||||
* @throws IllegalArgumentException if {@link PdxInstance} is {@literal null}.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see org.apache.geode.pdx.PdxInstanceFactory
|
||||
*/
|
||||
public PdxInstanceFactory copy(PdxInstance pdxInstance) {
|
||||
|
||||
assertNotNull(pdxInstance, "PdxInstance must not be null");
|
||||
|
||||
PdxInstanceFactory factory = getRegionService().createPdxInstanceFactory(pdxInstance.getClassName());
|
||||
|
||||
nullSafeList(pdxInstance.getFieldNames()).forEach(fieldName -> {
|
||||
|
||||
factory.writeObject(fieldName, pdxInstance.getField(fieldName));
|
||||
|
||||
if (pdxInstance.isIdentityField(fieldName)) {
|
||||
factory.markIdentityField(fieldName);
|
||||
}
|
||||
});
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link PdxInstance} from the given, required source {@link Object}.
|
||||
*
|
||||
* @param source {@link Object} being serialized to PDX; must not be {@literal null}.
|
||||
* @return a {@link Factory} used to create the {@link PdxInstance} from the given,
|
||||
* required source {@link Object}, which was serialized to PDX.
|
||||
* @throws IllegalArgumentException if {@link Object source} is {@literal null}.
|
||||
* @see Factory
|
||||
*/
|
||||
public Factory from(Object source) {
|
||||
|
||||
assertNotNull(source, "Source object to serialize to PDX must not be null");
|
||||
|
||||
RegionService regionService = getRegionService();
|
||||
|
||||
Optional.of(regionService)
|
||||
.filter(GemFireCache.class::isInstance)
|
||||
.map(GemFireCache.class::cast)
|
||||
.map(GemFireCache::getPdxReadSerialized)
|
||||
.filter(Boolean.TRUE::equals)
|
||||
.orElseThrow(() -> new IllegalStateException("PDX read-serialized must be set to true"));
|
||||
|
||||
PdxInstanceFactory factory = regionService.createPdxInstanceFactory(source.getClass().getName());
|
||||
|
||||
factory.writeObject("source", source);
|
||||
|
||||
AtomicReference<Object> resolvedSource = new AtomicReference<>(null);
|
||||
|
||||
return () -> Optional.of(factory)
|
||||
.map(PdxInstanceFactory::create)
|
||||
.map(pdxInstance -> resolvedSource.updateAndGet(it -> pdxInstance.getField("source")))
|
||||
.filter(PdxInstance.class::isInstance)
|
||||
.map(PdxInstance.class::cast)
|
||||
.orElseThrow(() -> {
|
||||
|
||||
String message = String.format("Expected an instance of PDX but was an instance of type [%s];"
|
||||
+ " Was PDX read-serialized set to true", nullSafeClassName(resolvedSource.get()));
|
||||
|
||||
return new IllegalArgumentException(message);
|
||||
});
|
||||
}
|
||||
|
||||
private String nullSafeClassName(Object target) {
|
||||
return target != null ? target.getClass().getName() : null;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Factory {
|
||||
|
||||
/**
|
||||
* Creates a {@link PdxInstance}.
|
||||
*
|
||||
* @return the created {@link PdxInstance}.
|
||||
* @throws IllegalArgumentException Depending on the implementation, an {@link IllegalArgumentException}
|
||||
* may be thrown if the {@link Object created object} is not of type {@link PdxInstance}.
|
||||
* @throws ClassCastException Depending on the implementation, a {@link ClassCastException} may be thrown
|
||||
* if the {@link Object created object} is not of type {@link PdxInstance}.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
*/
|
||||
PdxInstance create();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,500 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.pdx;
|
||||
|
||||
import static org.springframework.geode.util.GeodeAssertions.assertThat;
|
||||
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
|
||||
import org.apache.geode.internal.Sendable;
|
||||
import org.apache.geode.pdx.JSONFormatter;
|
||||
import org.apache.geode.pdx.PdxInstance;
|
||||
import org.apache.geode.pdx.WritablePdxInstance;
|
||||
|
||||
/**
|
||||
* The {@link PdxInstanceWrapper} class is an implementation of the {@link PdxInstance} interface
|
||||
* wrapping an existing {@link PdxInstance} object and decorating the functionality.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.function.Function
|
||||
* @see com.fasterxml.jackson.databind.ObjectMapper
|
||||
* @see org.apache.geode.pdx.JSONFormatter
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see org.apache.geode.pdx.WritablePdxInstance
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class PdxInstanceWrapper implements PdxInstance, Sendable {
|
||||
|
||||
public static final String AT_IDENTIFIER_FIELD_NAME = "@identifier";
|
||||
public static final String AT_TYPE_FIELD_NAME = "@type";
|
||||
public static final String CLASS_NAME_PROPERTY = "className";
|
||||
public static final String ID_FIELD_NAME = "id";
|
||||
protected static final String NO_FIELD_NAME = "";
|
||||
|
||||
protected static final String ARRAY_BEGIN = "[";
|
||||
protected static final String ARRAY_END = "]";
|
||||
protected static final String COMMA = ",";
|
||||
protected static final String EMPTY_STRING = "";
|
||||
protected static final String FIELD_TYPE_VALUE = "\"%1$s\"(%2$s): \"%3$s\"";
|
||||
protected static final String INDENT_STRING = "\t";
|
||||
protected static final String NEW_LINE = "\n";
|
||||
protected static final String COMMA_NEW_LINE = "," + NEW_LINE;
|
||||
protected static final String COMMA_SPACE = COMMA + " ";
|
||||
protected static final String OBJECT_BEGIN = "{";
|
||||
protected static final String OBJECT_END = "}";
|
||||
|
||||
/**
|
||||
* Smart, {@literal null-safe} factory method used to evaluate the given {@link Object} and wrap the {@link Object}
|
||||
* in a new instance of {@link PdxInstanceWrapper} if the {@link Object} is an instance of {@link PdxInstance}
|
||||
* or return the given {@link Object} as is.
|
||||
*
|
||||
* @param target {@link Object} to evaluate
|
||||
* @return the {@link Object} wrapped in a new instance of {@link PdxInstanceWrapper} if {@link Object}
|
||||
* is an instance of {@link PdxInstance}, otherwise returns the given {@link Object}.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see java.lang.Object
|
||||
* @see #from(PdxInstance)
|
||||
*/
|
||||
public static Object from(Object target) {
|
||||
|
||||
return target instanceof PdxInstance
|
||||
? from((PdxInstance) target)
|
||||
: target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method used to construct a new instance of {@link PdxInstanceWrapper} initialized with the given,
|
||||
* required {@link PdxInstance} used to back the wrapper.
|
||||
*
|
||||
* @param pdxInstance {@link PdxInstance} object used to back this wrapper; must not be {@literal null}.
|
||||
* @return a new instance of {@link PdxInstanceWrapper} initialized with the given {@link PdxInstance}.
|
||||
* @throws IllegalArgumentException if {@link PdxInstance} is {@literal null}.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see #PdxInstanceWrapper(PdxInstance)
|
||||
*/
|
||||
public static PdxInstanceWrapper from(PdxInstance pdxInstance) {
|
||||
|
||||
return pdxInstance instanceof PdxInstanceWrapper
|
||||
? (PdxInstanceWrapper) pdxInstance
|
||||
: new PdxInstanceWrapper(pdxInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe factory method used to unwrap the given {@link PdxInstance}.
|
||||
*
|
||||
* If the given {@link PdxInstance} is an instance of {@link PdxInstanceWrapper} then this factory method will
|
||||
* unwrap the {@link PdxInstanceWrapper} returning the underlying, {@link PdxInstanceWrapper#getDelegate() delegate}
|
||||
* {@link PdxInstance}. Otherwise, the given {@link PdxInstance} is returned.
|
||||
*
|
||||
* @param pdxInstance {@link PdxInstance} to unwrap; may be {@literal null}.
|
||||
* @return the unwrapped {@link PdxInstance}.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see #getDelegate()
|
||||
*/
|
||||
public static PdxInstance unwrap(PdxInstance pdxInstance) {
|
||||
|
||||
return pdxInstance instanceof PdxInstanceWrapper
|
||||
? ((PdxInstanceWrapper) pdxInstance).getDelegate()
|
||||
: pdxInstance;
|
||||
}
|
||||
|
||||
private final PdxInstance delegate;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of {@link PdxInstanceWrapper} initialized with the given, required {@link PdxInstance}
|
||||
* object used to back this wrapper.
|
||||
*
|
||||
* @param pdxInstance {@link PdxInstance} object used to back this wrapper; must not be {@literal null}.
|
||||
* @throws IllegalArgumentException if {@link PdxInstance} is {@literal null}.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
*/
|
||||
public PdxInstanceWrapper(PdxInstance pdxInstance) {
|
||||
|
||||
assertThat(pdxInstance).isNotNull();
|
||||
|
||||
this.delegate = pdxInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the configured, underlying {@link PdxInstance} backing this wrapper.
|
||||
*
|
||||
* @return a reference to the configured, underlying {@link PdxInstance} backing this wrapper;
|
||||
* never {@literal null}.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
*/
|
||||
public PdxInstance getDelegate() {
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Optional} reference to a configured Jackson {@link ObjectMapper} used to
|
||||
* deserialize the {@link String JSON} generated from {@link PdxInstance PDX} back into an {@link Object}.
|
||||
*
|
||||
* This method is meant ot be overridden by {@link Class subclasses}.
|
||||
*
|
||||
* @return an {@link Optional} {@link ObjectMapper}.
|
||||
* @see com.fasterxml.jackson.databind.ObjectMapper
|
||||
* @see java.util.Optional
|
||||
*/
|
||||
protected Optional<ObjectMapper> getObjectMapper() {
|
||||
|
||||
ObjectMapper objectMapper = newJsonMapperBuilder()
|
||||
.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false)
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true)
|
||||
.build()
|
||||
.findAndRegisterModules();
|
||||
|
||||
return Optional.of(objectMapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of Jackson's {@link JsonMapper}.
|
||||
*
|
||||
* @return a new instance of Jackson's {@link JsonMapper}; never {@literal null}.
|
||||
* @see com.fasterxml.jackson.databind.json.JsonMapper
|
||||
*/
|
||||
JsonMapper.Builder newJsonMapperBuilder() {
|
||||
return JsonMapper.builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public String getClassName() {
|
||||
return getDelegate().getClassName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isDeserializable() {
|
||||
return getDelegate().isDeserializable();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isEnum() {
|
||||
return getDelegate().isEnum();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Object getField(String fieldName) {
|
||||
return getDelegate().getField(fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public List<String> getFieldNames() {
|
||||
return getDelegate().getFieldNames();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the {@link Object identifier} for, or {@link PdxInstance#isIdentityField(String) identity} of,
|
||||
* this {@link PdxInstance}.
|
||||
*
|
||||
* @return the {@link Object identifier} for this {@link PdxInstance}; never {@literal null}.
|
||||
* @throws IllegalStateException if the {@link PdxInstance} does not have an id.
|
||||
* @see #isIdentityField(String)
|
||||
* @see #getField(String)
|
||||
* @see #getFieldNames()
|
||||
* @see #getId()
|
||||
*/
|
||||
public Object getIdentifier() {
|
||||
|
||||
Optional<String> identityFieldName = nullSafeList(getFieldNames()).stream()
|
||||
.filter(this::hasText)
|
||||
.filter(this::isIdentityField)
|
||||
.findFirst();
|
||||
|
||||
return identityFieldName
|
||||
.map(this::getField)
|
||||
.orElseGet(this::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a PDX {@link String field name} called {@literal id} on this {@link PdxInstance}
|
||||
* and returns its {@link Object value} as the {@link Object identifier} for,
|
||||
* or {@link PdxInstance#isIdentityField(String) identity} of, this {@link PdxInstance}.
|
||||
*
|
||||
* @return the {@link Object value} of the {@literal id} {@link String field} on this {@link PdxInstance}.
|
||||
* @throws IllegalStateException if this {@link PdxInstance} does not have an id.
|
||||
* @see #getAtIdentifier()
|
||||
* @see #getField(String)
|
||||
* @see #hasField(String)
|
||||
*/
|
||||
protected Object getId() {
|
||||
|
||||
return hasField(ID_FIELD_NAME)
|
||||
? getField(ID_FIELD_NAME)
|
||||
: getAtIdentifier();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a PDX {@link String field} declared by the {@literal @identifier} metadata {@link String field}
|
||||
* on this {@link PdxInstance} and returns the {@link Object value} of this {@link String field}
|
||||
* as the {@link Object identifier} for, or {@link PdxInstance#isIdentityField(String) identity} of,
|
||||
* this {@link PdxInstance}.
|
||||
*
|
||||
* @return the {@link Object value} of the {@link String field} declared in the {@literal @identifier} metadata
|
||||
* {@link String field} on this {@link PdxInstance}.
|
||||
* @throws IllegalStateException if the {@link PdxInstance} does not have an id.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
*/
|
||||
protected Object getAtIdentifier() {
|
||||
|
||||
return Optional.of(AT_IDENTIFIER_FIELD_NAME)
|
||||
.filter(this::hasField)
|
||||
.map(this::getField)
|
||||
.map(String::valueOf)
|
||||
.filter(this::hasField)
|
||||
.map(this::getField)
|
||||
.orElseThrow(() -> new IllegalStateException(String.format("PdxInstance for type [%1$s] has no %2$s",
|
||||
getClassName(), resolveMessageForIdentifierError(this))));
|
||||
}
|
||||
|
||||
private String resolveMessageForIdentifierError(PdxInstance pdxInstance) {
|
||||
|
||||
String message = "declared identifier";
|
||||
|
||||
if (pdxInstance.hasField(ID_FIELD_NAME)) {
|
||||
message = "id";
|
||||
}
|
||||
else if (pdxInstance.hasField(AT_IDENTIFIER_FIELD_NAME)) {
|
||||
|
||||
Object atIdentifierFieldValue = pdxInstance.getField(AT_IDENTIFIER_FIELD_NAME);
|
||||
|
||||
String resolvedIdentifierFieldName = Objects.nonNull(atIdentifierFieldValue)
|
||||
? atIdentifierFieldValue.toString().trim()
|
||||
: NO_FIELD_NAME;
|
||||
|
||||
boolean identifierFieldNameWasDeclaredAndIsValid = pdxInstance.hasField(resolvedIdentifierFieldName);
|
||||
|
||||
Object identifier = identifierFieldNameWasDeclaredAndIsValid
|
||||
? pdxInstance.getField(resolvedIdentifierFieldName)
|
||||
: null;
|
||||
|
||||
String ifMessage = "value [%s] for field [%s] declared in [%s]";
|
||||
String elseMessage = "field [%s] declared in [%s]";
|
||||
|
||||
message = identifierFieldNameWasDeclaredAndIsValid
|
||||
? String.format(ifMessage, identifier, resolvedIdentifierFieldName, AT_IDENTIFIER_FIELD_NAME)
|
||||
: String.format(elseMessage, resolvedIdentifierFieldName, AT_IDENTIFIER_FIELD_NAME);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isIdentityField(String fieldName) {
|
||||
return getDelegate().isIdentityField(fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Materializes an {@link Object} from the PDX bytes described by this {@link PdxInstance}.
|
||||
*
|
||||
* If these PDX bytes describe an {@link Object} parsed from JSON, then the JSON is reconstructed from
|
||||
* this {@link PdxInstance} and mapped to an instance of the {@link Class type} identified by
|
||||
* the {@literal @type} metadata PDX {@link String field} using Jackson's {@link ObjectMapper}.
|
||||
*
|
||||
* @return an {@link Object} constructed from the PDX bytes described by this {@link PdxInstance}.
|
||||
* @see com.fasterxml.jackson.databind.ObjectMapper
|
||||
* @see java.lang.Object
|
||||
* @see #getObjectMapper()
|
||||
*/
|
||||
@Override
|
||||
public Object getObject() {
|
||||
|
||||
return getObjectMapper()
|
||||
.filter(objectMapper -> JSONFormatter.JSON_CLASSNAME.equals(getClassName()))
|
||||
.filter(objectMapper -> hasField(AT_TYPE_FIELD_NAME))
|
||||
.<Object>map(objectMapper -> {
|
||||
try {
|
||||
|
||||
String typeName = String.valueOf(getField(AT_TYPE_FIELD_NAME));
|
||||
|
||||
Class<?> type = Class.forName(typeName);
|
||||
|
||||
String json = jsonFormatterToJson(getDelegate());
|
||||
|
||||
return objectMapper.readValue(json, type);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
// TODO Log Throwable?
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.orElseGet(() -> getDelegate().getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link JSONFormatter#toJSON(PdxInstance)} to convert the {@link PdxInstance} into {@link String JSON}.
|
||||
*
|
||||
* @param pdxInstance {@link PdxInstance} to convert to {@link String JSON}.
|
||||
* @return {@link String JSON} generated from the given {@link PdxInstance}.
|
||||
* @see org.apache.geode.pdx.JSONFormatter#toJSON(PdxInstance)
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
*/
|
||||
String jsonFormatterToJson(PdxInstance pdxInstance) {
|
||||
return JSONFormatter.toJSON(pdxInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public WritablePdxInstance createWriter() {
|
||||
return getDelegate().createWriter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean hasField(String fieldName) {
|
||||
return getDelegate().hasField(fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void sendTo(DataOutput out) throws IOException {
|
||||
|
||||
PdxInstance delegate = getDelegate();
|
||||
|
||||
if (delegate instanceof Sendable) {
|
||||
((Sendable) delegate).sendTo(out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link String} representation of this {@link PdxInstance}.
|
||||
*
|
||||
* @return a {@link String} representation of this {@link PdxInstance}.
|
||||
* @see java.lang.String
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
//return getDelegate().toString();
|
||||
return toString(this);
|
||||
}
|
||||
|
||||
private String toString(PdxInstance pdx) {
|
||||
return toString(pdx, "");
|
||||
}
|
||||
|
||||
private String toString(PdxInstance pdx, String indent) {
|
||||
|
||||
if (Objects.nonNull(pdx)) {
|
||||
|
||||
StringBuilder buffer = new StringBuilder(OBJECT_BEGIN).append(NEW_LINE);
|
||||
|
||||
String fieldIndent = indent + INDENT_STRING;
|
||||
|
||||
buffer.append(fieldIndent).append(formatFieldValue(CLASS_NAME_PROPERTY, pdx.getClassName()));
|
||||
|
||||
for (String fieldName : nullSafeList(pdx.getFieldNames())) {
|
||||
|
||||
Object fieldValue = pdx.getField(fieldName);
|
||||
|
||||
String valueString = toStringObject(fieldValue, fieldIndent);
|
||||
|
||||
buffer.append(COMMA_NEW_LINE);
|
||||
buffer.append(fieldIndent).append(formatFieldValue(fieldName, valueString));
|
||||
}
|
||||
|
||||
buffer.append(NEW_LINE).append(indent).append(OBJECT_END);
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String toStringArray(Object value, String indent) {
|
||||
|
||||
Object[] array = (Object[]) value;
|
||||
|
||||
StringBuilder buffer = new StringBuilder(ARRAY_BEGIN);
|
||||
|
||||
boolean addComma = false;
|
||||
|
||||
for (Object element : array) {
|
||||
buffer.append(addComma ? COMMA_SPACE : EMPTY_STRING);
|
||||
buffer.append(toStringObject(element, indent));
|
||||
addComma = true;
|
||||
}
|
||||
|
||||
buffer.append(ARRAY_END);
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private String toStringObject(Object value, String indent) {
|
||||
|
||||
return isPdxInstance(value) ? toString((PdxInstance) value, indent)
|
||||
: isArray(value) ? toStringArray(value, indent)
|
||||
: String.valueOf(value);
|
||||
}
|
||||
|
||||
private String formatFieldValue(String fieldName, Object fieldValue) {
|
||||
return String.format(FIELD_TYPE_VALUE, fieldName, nullSafeType(fieldValue), fieldValue);
|
||||
}
|
||||
|
||||
private boolean hasText(String value) {
|
||||
return value != null && !value.trim().isEmpty();
|
||||
}
|
||||
|
||||
private boolean isArray(Object value) {
|
||||
return Objects.nonNull(value) && value.getClass().isArray();
|
||||
}
|
||||
|
||||
private boolean isPdxInstance(Object value) {
|
||||
return value instanceof PdxInstance;
|
||||
}
|
||||
|
||||
private <T> List<T> nullSafeList(List<T> list) {
|
||||
return list != null ? list : Collections.emptyList();
|
||||
}
|
||||
|
||||
private Class<?> nullSafeType(Object value) {
|
||||
return value != null ? value.getClass() : Object.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.security;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.distributed.DistributedMember;
|
||||
import org.apache.geode.security.AuthInitialize;
|
||||
import org.apache.geode.security.AuthenticationFailedException;
|
||||
|
||||
import org.springframework.geode.util.GeodeConstants;
|
||||
|
||||
/**
|
||||
* Simple, test {@link AuthInitialize} implementation.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.security.AuthInitialize
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class TestAuthInitialize implements AuthInitialize {
|
||||
|
||||
private static final String DEFAULT_USERNAME = "test";
|
||||
private static final String DEFAULT_PASSWORD = DEFAULT_USERNAME;
|
||||
|
||||
public static TestAuthInitialize create() {
|
||||
return new TestAuthInitialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getCredentials(Properties securityProperties, DistributedMember server, boolean isPeer)
|
||||
throws AuthenticationFailedException {
|
||||
|
||||
Properties credentials = new Properties();
|
||||
|
||||
credentials.setProperty(GeodeConstants.USERNAME,
|
||||
securityProperties.getProperty(GeodeConstants.USERNAME, DEFAULT_USERNAME));
|
||||
|
||||
credentials.setProperty(GeodeConstants.PASSWORD,
|
||||
securityProperties.getProperty(GeodeConstants.PASSWORD, DEFAULT_PASSWORD));
|
||||
|
||||
return credentials;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.security;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.security.Principal;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.security.AuthenticationFailedException;
|
||||
|
||||
import org.springframework.geode.util.GeodeConstants;
|
||||
|
||||
/**
|
||||
* Simple, test {@link org.apache.geode.security.SecurityManager}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.security.Principal
|
||||
* @see java.util.Properties
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class TestSecurityManager implements org.apache.geode.security.SecurityManager {
|
||||
|
||||
@Override
|
||||
public Object authenticate(Properties credentials) throws AuthenticationFailedException {
|
||||
|
||||
String username = credentials.getProperty(GeodeConstants.USERNAME);
|
||||
String password = credentials.getProperty(GeodeConstants.PASSWORD);
|
||||
|
||||
if (!String.valueOf(username).equals(password)) {
|
||||
throw new AuthenticationFailedException(String.format("User [%s] could not be authenticated", username));
|
||||
}
|
||||
|
||||
return User.create(username);
|
||||
}
|
||||
|
||||
public static class User implements Comparable<User>, Principal, Serializable {
|
||||
|
||||
public static User create(String name) {
|
||||
return new User(name);
|
||||
}
|
||||
|
||||
private final String name;
|
||||
|
||||
public User(String name) {
|
||||
|
||||
if (name == null || name.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("Username is required");
|
||||
}
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(User user) {
|
||||
return this.getName().compareTo(user.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof User)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
User that = (User) obj;
|
||||
|
||||
return this.getName().equals(that.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int hashValue = 17;
|
||||
|
||||
hashValue = 37 * hashValue + getName().hashCode();
|
||||
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.util;
|
||||
|
||||
import static org.springframework.geode.util.GeodeAssertions.assertThat;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.DataPolicy;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.RegionAttributes;
|
||||
import org.apache.geode.cache.RegionService;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.Pool;
|
||||
import org.apache.geode.internal.cache.GemFireCacheImpl;
|
||||
|
||||
/**
|
||||
* Abstract utility class for working with Apache Geode cache instances, such as {@link ClientCache}
|
||||
* and {@literal peer} {@link Cache} instances.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.DataPolicy
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.RegionAttributes
|
||||
* @see org.apache.geode.cache.RegionService
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public abstract class CacheUtils {
|
||||
|
||||
/**
|
||||
* Collects all {@link Object values} from the given {@link Region}.
|
||||
*
|
||||
* This method is capable of pulling {@link Object values} from either {@literal client}
|
||||
* or {@literal peer} {@link Region Regions}.
|
||||
*
|
||||
* @param <T> {@link Class type} of the {@link Region} {@link Object values}.
|
||||
* @param region {@link Region} from which to collect the {@link Object values}.
|
||||
* @return a {@link Collection} of all {@link Object values} from the given {@link Region}.
|
||||
* @throws IllegalArgumentException if {@link Region} is {@literal null}.
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see java.util.Collection
|
||||
*/
|
||||
// TODO Add Predicate-based Filtering
|
||||
public static <T> Collection<T> collectValues(Region<?, T> region) {
|
||||
|
||||
assertThat(region).isNotNull();
|
||||
|
||||
return isClientRegion(region)
|
||||
? clientRegionValues(region)
|
||||
: localRegionValues(region);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects values from the given {@literal client} {@link Region}.
|
||||
*
|
||||
* @param <T> {@link Class type} of the {@link Region Region's} values.
|
||||
* @param region {@link Region} from which to collect values.
|
||||
* @return a {@link Collection} of the {@literal client} {@link Region Region's} values.
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #clientRegionValuesFromServer(Region)
|
||||
* @see #localRegionValues(Region)
|
||||
* @see #isProxyRegion(Region)
|
||||
*/
|
||||
private static <T> Collection<T> clientRegionValues(Region<?, T> region) {
|
||||
|
||||
return isProxyRegion(region)
|
||||
? clientRegionValuesFromServer(region)
|
||||
: localRegionValues(region);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collections all values from the {@literal client} {@link Region} by pulling the values down from the server.
|
||||
*
|
||||
* @param <T> {@link Class type} of the {@link Region Region's} values.
|
||||
* @param region {@link Region} from which to collect values.
|
||||
* @return a {@link Collection} containing the values from the {@literal client} {@link Region} on the server.
|
||||
* @see org.apache.geode.cache.Region#keySetOnServer()
|
||||
* @see #getAll(Region, Set)
|
||||
*/
|
||||
private static <T> Collection<T> clientRegionValuesFromServer(Region<?, T> region) {
|
||||
|
||||
Set<?> keys = nullSafeSet(region.keySetOnServer());
|
||||
|
||||
return !keys.isEmpty() ? getAll(region, keys) : Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all values from the given {@link Region} mapped to the specified {@link Set keys}.
|
||||
*
|
||||
* @param <T> {@link Class type} of the {@link Region Region's} values.
|
||||
* @param region {@link Region} from which to get all values.
|
||||
* @param keys {@link Set} of keys targeting the values to retrieve.
|
||||
* @return a {@link Collection} of the {@link Region Region's} values.
|
||||
* @see org.apache.geode.cache.Region#getAll(Collection)
|
||||
*/
|
||||
private static <T> Collection<T> getAll(Region<?, T> region, Set<?> keys) {
|
||||
return nullSafeMap(region.getAll(keys)).values();
|
||||
// Fallback procedure if region.getAll(keys) is buggered
|
||||
//return keys.stream().map(region::get).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects values from the given {@link Region}, locally.
|
||||
*
|
||||
* @param <T> {@link Class type} of the {@link Region Region's} values.
|
||||
* @param region {@link Region} from which to collect values.
|
||||
* @return a {@link Collection} of the {@link Region Region's} values.
|
||||
* @see org.apache.geode.cache.Region#values()
|
||||
*/
|
||||
private static <T> Collection<T> localRegionValues(Region<?, T> region) {
|
||||
return region.values();
|
||||
}
|
||||
|
||||
private static boolean hasText(String value) {
|
||||
return value != null && !value.trim().isEmpty();
|
||||
}
|
||||
|
||||
private static <K, V> Map<K, V> nullSafeMap(Map<K, V> map) {
|
||||
return map != null ? map :Collections.emptyMap();
|
||||
}
|
||||
|
||||
private static <T> Set<T> nullSafeSet(Set<T> set) {
|
||||
return set != null ? set : Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe method to determine whether the given {@link RegionService} is an instance of {@link ClientCache}.
|
||||
*
|
||||
* The problem is, {@link GemFireCacheImpl} implements both the (peer) {@link Cache}
|
||||
* and {@link ClientCache} interfaces. #sigh
|
||||
*
|
||||
* @param regionService {@link RegionService} to evaluate.
|
||||
* @return a boolean value indicating whether the {@link RegionService} an instance of {@link ClientCache}.
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.RegionService
|
||||
*/
|
||||
public static boolean isClientCache(RegionService regionService) {
|
||||
|
||||
boolean result = regionService instanceof ClientCache;
|
||||
|
||||
if (regionService instanceof GemFireCacheImpl) {
|
||||
result &= ((GemFireCacheImpl) regionService).isClient();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe method to determine whether the given {@link Region} is a {@literal client} {@link Region}
|
||||
* in a {@link ClientCache}.
|
||||
*
|
||||
* @param region {@link Region} to evaluate.
|
||||
* @return a boolean value indicating whether the given {@link Region} is a {@literal client} {@link Region}.
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #isClientCache(RegionService)
|
||||
*/
|
||||
public static boolean isClientRegion(Region<?, ?> region) {
|
||||
|
||||
return region != null
|
||||
&& (isClientCache(region.getRegionService()) || isRegionWithPool(region));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe method to determine whether the given {@link RegionService} is an instance of
|
||||
* a {@literal peer} {@link Cache}.
|
||||
*
|
||||
* The problem is, {@link GemFireCacheImpl} implements both the (peer) {@link Cache}
|
||||
* and {@link ClientCache} interfaces. #sigh
|
||||
*
|
||||
* @param regionService {@link RegionService} to evaluate.
|
||||
* @return a boolean value indicating whether the {@link RegionService} is an instance of
|
||||
* a {@literal peer} {@link Cache}.
|
||||
* @see org.apache.geode.cache.RegionService
|
||||
* @see org.apache.geode.cache.Cache
|
||||
*/
|
||||
public static boolean isPeerCache(RegionService regionService) {
|
||||
|
||||
boolean result = regionService instanceof Cache;
|
||||
|
||||
if (regionService instanceof GemFireCacheImpl) {
|
||||
result &= !((GemFireCacheImpl) regionService).isClient();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe method to determine whether the given {@link Region} is a {@literal peer} {@link Region}
|
||||
* in a {@literal peer} {@link Cache}.
|
||||
*
|
||||
* @param region {@link Region} to evaluate.
|
||||
* @return a boolean value indicating whether the given {@link Region} is a {@literal peer} {@link Region}.
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #isPeerCache(RegionService)
|
||||
*/
|
||||
public static boolean isPeerRegion(Region<?, ?> region) {
|
||||
return region != null && !isClientRegion(region);
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe method to determine whether the given {@link Region} is a [client] {@literal PROXY} {@link Region}.
|
||||
*
|
||||
* The {@link Region} is a {@literal PROXY} if the {@link DataPolicy} is {@link DataPolicy#EMPTY}
|
||||
* or the {@link Region} has a configured {@link Pool}.
|
||||
*
|
||||
* @param region {@link Region} to evaluate.
|
||||
* @return a boolean value to determine whether the {@link Region} is a [client] {@literal PROXY} {@link Region}.
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #isRegionWithPool(Region)
|
||||
*/
|
||||
public static boolean isProxyRegion(Region<?, ?> region) {
|
||||
|
||||
return region != null
|
||||
&& region.getAttributes() != null
|
||||
&& (DataPolicy.EMPTY.equals(region.getAttributes().getDataPolicy())
|
||||
|| isRegionWithPool(region));
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe method to determine whether the given {@link Region} was configured with a {@link Pool}.
|
||||
*
|
||||
* A {@link Region} configured with a {@link Pool} (by {@link String name} specified in the {@link RegionAttributes})
|
||||
* is a strong indicator that the {@link Region} is a {@literal client} {@link Region}.
|
||||
*
|
||||
* @param region {@link Region} to evaluate.
|
||||
* @return a boolean to determine whether the given {@link Region} was configured with a {@link Pool}.
|
||||
* @see org.apache.geode.cache.client.Pool
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
public static boolean isRegionWithPool(Region<?, ?> region) {
|
||||
|
||||
return Optional.ofNullable(region)
|
||||
.map(Region::getAttributes)
|
||||
.map(RegionAttributes::getPoolName)
|
||||
.filter(CacheUtils::hasText)
|
||||
.isPresent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.util;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.distributed.internal.InternalDistributedSystem;
|
||||
import org.apache.geode.internal.cache.AbstractRegion;
|
||||
import org.apache.geode.internal.cache.GemFireCacheImpl;
|
||||
|
||||
/**
|
||||
* Abstract utility class containing different assertions for Apache Geode objects, such as a {@link GemFireCache}
|
||||
* or {@link Region}, and so on.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class GeodeAssertions {
|
||||
|
||||
/**
|
||||
* Asserts that given {@link Object} upholds certain contractual obligations.
|
||||
*
|
||||
* @param <T> {@link Class type} of the given {@link Object}.
|
||||
* @param obj {@link Object} being evaluated in the assertion.
|
||||
* @return a new instance of {@link AssertThat} using the given {@link Object}
|
||||
* as the {@link AssertThat#getSubject() subject} of the assertion.
|
||||
* @see java.lang.Object
|
||||
* @see AssertThat
|
||||
*/
|
||||
public static <T> AssertThat<T> assertThat(T obj) {
|
||||
return () -> obj;
|
||||
}
|
||||
|
||||
private static void assertIsInstanceOf(Object target, Class<?> type) {
|
||||
|
||||
if (!type.isInstance(target)) {
|
||||
throw new AssertionError(String.format("[%1$s] is not an instance of [%2$s]",
|
||||
nullSafeTypeName(target), nullSafeTypeName(type)));
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertIsNotInstanceOf(Object target, Class<?> type) {
|
||||
|
||||
if (type.isInstance(target)) {
|
||||
throw new AssertionError(String.format("[%1%s] is an instance of [%2$s]",
|
||||
nullSafeTypeName(target), nullSafeTypeName(type)));
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertIsNotNull(Object target) {
|
||||
|
||||
if (Objects.isNull(target)) {
|
||||
throw new IllegalArgumentException("Argument must not be null");
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> nullSafeType(Object obj) {
|
||||
return obj != null ? obj.getClass() : null;
|
||||
}
|
||||
|
||||
private static String nullSafeTypeName(Class<?> type) {
|
||||
return type != null ? type.getName() : null;
|
||||
}
|
||||
|
||||
public static String nullSafeTypeName(Object obj) {
|
||||
return nullSafeTypeName(nullSafeType(obj));
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link AssertThat} {@link FunctionalInterface interface} defines a contract for making assertion about
|
||||
* a given {@link Object} used as the {@link #getSubject() subject} of the assert statement.
|
||||
*
|
||||
* @param <T> {@link Class type} of the {@link Object} that is the {@link #getSubject() subject} of the assertion.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface AssertThat<T> {
|
||||
|
||||
/**
|
||||
* Returns the {@link Object} used as the subject of this assertion.
|
||||
*
|
||||
* @return the {@link Object} used as the subject of this assertion.
|
||||
* @see java.lang.Object
|
||||
*/
|
||||
T getSubject();
|
||||
|
||||
/**
|
||||
* Asserts the {@link #getSubject() subject} is not {@literal null}.
|
||||
*/
|
||||
default void isNotNull() {
|
||||
assertIsNotNull(getSubject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the {@link #getSubject()} is an instance of {@link GemFireCacheImpl}.
|
||||
*/
|
||||
default void isInstanceOfGemFireCacheImpl() {
|
||||
assertIsInstanceOf(getSubject(), GemFireCacheImpl.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the {@link #getSubject()} is an instance of {@link InternalDistributedSystem}.
|
||||
*/
|
||||
default void isInstanceOfInternalDistributedSystem() {
|
||||
assertIsInstanceOf(getSubject(), InternalDistributedSystem.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the {@link #getSubject()} is not an instance of {@link AbstractRegion}.
|
||||
*/
|
||||
default void isNotInstanceOfAbstractRegion() {
|
||||
assertIsNotInstanceOf(getSubject(), AbstractRegion.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the {@link #getSubject()} is not an instance of {@link GemFireCacheImpl}.
|
||||
*/
|
||||
default void isNotInstanceOfGemFireCacheImpl() {
|
||||
assertIsNotInstanceOf(getSubject(), GemFireCacheImpl.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the {@link #getSubject()} is not an instance of {@link InternalDistributedSystem}.
|
||||
*/
|
||||
default void isNotInstanceOfInternalDistributedSystem() {
|
||||
assertIsNotInstanceOf(getSubject(), InternalDistributedSystem.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.util;
|
||||
|
||||
import org.apache.geode.distributed.ConfigurationProperties;
|
||||
import org.apache.geode.management.internal.security.ResourceConstants;
|
||||
|
||||
/**
|
||||
* Interface encapsulating common Apache Geode constants used by SBDG.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.distributed.ConfigurationProperties
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public interface GeodeConstants {
|
||||
|
||||
String GEMFIRE_PROPERTY_PREFIX = "gemfire.";
|
||||
|
||||
// Logging Constants (referring to Properties)
|
||||
String LOG_DISK_SPACE_LIMIT = ConfigurationProperties.LOG_DISK_SPACE_LIMIT;
|
||||
String LOG_FILE = ConfigurationProperties.LOG_FILE;
|
||||
String LOG_FILE_SIZE_LIMIT = ConfigurationProperties.LOG_FILE_SIZE_LIMIT;
|
||||
String LOG_LEVEL = ConfigurationProperties.LOG_LEVEL;
|
||||
|
||||
// Security Constants (referring to Properties)
|
||||
String PASSWORD = ResourceConstants.PASSWORD;
|
||||
String USERNAME = ResourceConstants.USER_NAME;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.util.function;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* {@link Iterable} of {@link Method} invocation {@link Object arguments}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.lang.Iterable
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class InvocationArguments implements Iterable<Object> {
|
||||
|
||||
public static InvocationArguments from(Object... arguments) {
|
||||
return new InvocationArguments(arguments);
|
||||
}
|
||||
|
||||
private final Object[] arguments;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of {@link InvocationArguments} initialized with the given array of
|
||||
* {@link Object arguments}.
|
||||
*
|
||||
* @param arguments array of {@link Object arguments} indicating the values passed to the {@link Method} invocation
|
||||
* parameters; may be {@literal null}.
|
||||
*/
|
||||
public InvocationArguments(Object[] arguments) {
|
||||
this.arguments = arguments != null ? arguments : new Object[0];
|
||||
}
|
||||
|
||||
protected Object[] getArguments() {
|
||||
return this.arguments;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T getArgumentAt(int index) {
|
||||
return (T) getArguments()[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Object> iterator() {
|
||||
|
||||
return new Iterator<Object>() {
|
||||
|
||||
int index = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return this.index < InvocationArguments.this.getArguments().length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object next() {
|
||||
return InvocationArguments.this.getArguments()[this.index++];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return this.arguments.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(getArguments());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.util.function;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* {@link Consumer} like interface accepting 3 arguments.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.function.Consumer
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface TriConsumer<T, U, V> {
|
||||
|
||||
/**
|
||||
* Performs a given operation on the 3 arguments.
|
||||
*
|
||||
* @param t first {@link Object argument}.
|
||||
* @param u second {@link Object argument}.
|
||||
* @param v third {@link Object argument}.
|
||||
*/
|
||||
void accept(T t, U u, V v);
|
||||
|
||||
/**
|
||||
* Composes this {@link TriConsumer} with the given {@link TriConsumer} after this {@link TriConsumer}.
|
||||
*
|
||||
* @param after {@link TriConsumer} to composed with this {@link TriConsumer}; must not be {@literal null}.
|
||||
* @return a new {@link TriConsumer} with the given {@link TriConsumer} composed after this {@link TriConsumer}.
|
||||
* @throws NullPointerException if {@link TriConsumer} is {@literal null}.
|
||||
*/
|
||||
default TriConsumer<T, U, V> andThen(TriConsumer<T, U, V> after) {
|
||||
|
||||
Objects.requireNonNull(after);
|
||||
|
||||
return (t, u, v) -> {
|
||||
accept(t, u, v);
|
||||
after.accept(t, u, v);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.util.function;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* {@link Consumer} implementation accepting a tuple of {@link InvocationArguments arguments}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.function.Consumer
|
||||
* @see org.springframework.geode.util.function.InvocationArguments
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface TupleConsumer extends Consumer<InvocationArguments> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.app;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.ClientCacheFactory;
|
||||
import org.apache.geode.cache.client.ClientRegionShortcut;
|
||||
|
||||
/**
|
||||
* An example Apache Geode {@link ClientCache} application.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.Properties
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.client.ClientCacheFactory
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ApacheGeodeClientApplication implements Runnable {
|
||||
|
||||
private static final ClientRegionShortcut CLIENT_REGION_SHORTCUT = ClientRegionShortcut.LOCAL;
|
||||
|
||||
private static final String APPLICATION_NAME = ApacheGeodeClientApplication.class.getSimpleName();
|
||||
private static final String GEMFIRE_LOG_LEVEL = "info";
|
||||
|
||||
private static final String[] EMPTY_ARGUMENTS = {};
|
||||
|
||||
public static void main(String[] args) {
|
||||
new ApacheGeodeClientApplication(args).run();
|
||||
}
|
||||
|
||||
private final String[] arguments;
|
||||
|
||||
public ApacheGeodeClientApplication(String[] arguments) {
|
||||
this.arguments = arguments != null ? arguments : EMPTY_ARGUMENTS;
|
||||
}
|
||||
|
||||
protected String[] getArguments() {
|
||||
return this.arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
run(getArguments());
|
||||
}
|
||||
|
||||
public void run(String[] arguments) {
|
||||
|
||||
ClientCache clientCache = registerShutdownHook(newClientCache(gemfireProperties()));
|
||||
|
||||
Region<Object, Object> example = newClientRegion(clientCache, "Example");
|
||||
|
||||
doDataAccessOperationsTest(example);
|
||||
}
|
||||
|
||||
protected Properties gemfireProperties() {
|
||||
|
||||
Properties gemfireProperties = new Properties();
|
||||
|
||||
gemfireProperties.setProperty("name", APPLICATION_NAME);
|
||||
gemfireProperties.setProperty("log-level", GEMFIRE_LOG_LEVEL);
|
||||
// See: https://issues.apache.org/jira/browse/GEODE-7891
|
||||
//gemfireProperties.setProperty("geode.disallow-internal-messages-without-credentials", Boolean.TRUE.toString());
|
||||
//gemfireProperties.setProperty("tombstone-gc-threshold", "100");
|
||||
|
||||
return gemfireProperties;
|
||||
}
|
||||
|
||||
protected ClientCache newClientCache(Properties gemfireProperties) {
|
||||
return new ClientCacheFactory(gemfireProperties).create();
|
||||
}
|
||||
|
||||
protected <K, V> Region<K, V> newClientRegion(ClientCache clientCache, String regionName) {
|
||||
return clientCache.<K, V>createClientRegionFactory(CLIENT_REGION_SHORTCUT).create(regionName);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <K, V> Region<K, V> doDataAccessOperationsTest(Region<Object, Object> region) {
|
||||
|
||||
assertThat(region.put(1, "TEST")).isNull();
|
||||
assertThat(region.get(1)).isEqualTo("TEST");
|
||||
|
||||
return (Region<K, V>) region;
|
||||
}
|
||||
|
||||
protected ClientCache registerShutdownHook(ClientCache clientCache) {
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() ->
|
||||
Optional.ofNullable(clientCache).ifPresent(ClientCache::close),
|
||||
"ClientCache Shutdown Hook"));
|
||||
|
||||
return clientCache;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.cache;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import org.apache.geode.cache.EntryEvent;
|
||||
import org.apache.geode.cache.RegionEvent;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link AbstractCommonEventProcessingCacheListener}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.cache.CacheListener
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractCommonEventProcessingCacheListenerUnitTests {
|
||||
|
||||
@Mock
|
||||
private EntryEvent<Object, Object> mockEntryEvent;
|
||||
|
||||
@Mock
|
||||
private RegionEvent<Object, Object> mockRegionEvent;
|
||||
|
||||
@Spy
|
||||
private AbstractCommonEventProcessingCacheListener<Object, Object> cacheListener;
|
||||
|
||||
@Test
|
||||
public void afterCreateCallsProcessEntryEventWithCreate() {
|
||||
|
||||
this.cacheListener.afterCreate(this.mockEntryEvent);
|
||||
|
||||
verify(this.cacheListener, times(1)).afterCreate(eq(this.mockEntryEvent));
|
||||
|
||||
verify(this.cacheListener, times(1)).processEntryEvent(eq(this.mockEntryEvent),
|
||||
eq(AbstractCommonEventProcessingCacheListener.EntryEventType.CREATE));
|
||||
|
||||
verifyNoMoreInteractions(this.cacheListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterDestroyCallsProcessEntryEventWithDestroy() {
|
||||
|
||||
this.cacheListener.afterDestroy(this.mockEntryEvent);
|
||||
|
||||
verify(this.cacheListener, times(1)).afterDestroy(eq(this.mockEntryEvent));
|
||||
|
||||
verify(this.cacheListener, times(1)).processEntryEvent(eq(this.mockEntryEvent),
|
||||
eq(AbstractCommonEventProcessingCacheListener.EntryEventType.DESTROY));
|
||||
|
||||
verifyNoMoreInteractions(this.cacheListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterInvalidateCallsProcessEntryEventWithInvalidate() {
|
||||
|
||||
this.cacheListener.afterInvalidate(this.mockEntryEvent);
|
||||
|
||||
verify(this.cacheListener, times(1)).afterInvalidate(eq(this.mockEntryEvent));
|
||||
|
||||
verify(this.cacheListener, times(1)).processEntryEvent(eq(this.mockEntryEvent),
|
||||
eq(AbstractCommonEventProcessingCacheListener.EntryEventType.INVALIDATE));
|
||||
|
||||
verifyNoMoreInteractions(this.cacheListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterUpdateCallsProcessEntryEventWithUpdate() {
|
||||
|
||||
this.cacheListener.afterUpdate(this.mockEntryEvent);
|
||||
|
||||
verify(this.cacheListener, times(1)).afterUpdate(eq(this.mockEntryEvent));
|
||||
|
||||
verify(this.cacheListener, times(1)).processEntryEvent(eq(this.mockEntryEvent),
|
||||
eq(AbstractCommonEventProcessingCacheListener.EntryEventType.UPDATE));
|
||||
|
||||
verifyNoMoreInteractions(this.cacheListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterRegionClearCallsProcessRegionEventWithClear() {
|
||||
|
||||
this.cacheListener.afterRegionClear(this.mockRegionEvent);
|
||||
|
||||
verify(this.cacheListener, times(1)).afterRegionClear(eq(this.mockRegionEvent));
|
||||
|
||||
verify(this.cacheListener, times(1)).processRegionEvent(eq(this.mockRegionEvent),
|
||||
eq(AbstractCommonEventProcessingCacheListener.RegionEventType.CLEAR));
|
||||
|
||||
verifyNoMoreInteractions(this.cacheListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterRegionCreateCallsProcessRegionEventWithCreate() {
|
||||
|
||||
this.cacheListener.afterRegionCreate(this.mockRegionEvent);
|
||||
|
||||
verify(this.cacheListener, times(1)).afterRegionCreate(eq(this.mockRegionEvent));
|
||||
|
||||
verify(this.cacheListener, times(1)).processRegionEvent(eq(this.mockRegionEvent),
|
||||
eq(AbstractCommonEventProcessingCacheListener.RegionEventType.CREATE));
|
||||
|
||||
verifyNoMoreInteractions(this.cacheListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterRegionDestroyCallsProcessRegionEventWithCreate() {
|
||||
|
||||
this.cacheListener.afterRegionDestroy(this.mockRegionEvent);
|
||||
|
||||
verify(this.cacheListener, times(1)).afterRegionDestroy(eq(this.mockRegionEvent));
|
||||
|
||||
verify(this.cacheListener, times(1)).processRegionEvent(eq(this.mockRegionEvent),
|
||||
eq(AbstractCommonEventProcessingCacheListener.RegionEventType.DESTROY));
|
||||
|
||||
verifyNoMoreInteractions(this.cacheListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterRegionInvalidateCallsProcessRegionEventWithInvalidate() {
|
||||
|
||||
this.cacheListener.afterRegionInvalidate(this.mockRegionEvent);
|
||||
|
||||
verify(this.cacheListener, times(1)).afterRegionInvalidate(eq(this.mockRegionEvent));
|
||||
|
||||
verify(this.cacheListener, times(1)).processRegionEvent(eq(this.mockRegionEvent),
|
||||
eq(AbstractCommonEventProcessingCacheListener.RegionEventType.INVALIDATE));
|
||||
|
||||
verifyNoMoreInteractions(this.cacheListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterRegionLiveCallsProcessRegionEventWithLive() {
|
||||
|
||||
this.cacheListener.afterRegionLive(this.mockRegionEvent);
|
||||
|
||||
verify(this.cacheListener, times(1)).afterRegionLive(eq(this.mockRegionEvent));
|
||||
|
||||
verify(this.cacheListener, times(1)).processRegionEvent(eq(this.mockRegionEvent),
|
||||
eq(AbstractCommonEventProcessingCacheListener.RegionEventType.LIVE));
|
||||
|
||||
verifyNoMoreInteractions(this.cacheListener);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.cache;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link SimpleCacheResolver}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.springframework.geode.cache.SimpleCacheResolver
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class SimpleCacheResolverUnitTests {
|
||||
|
||||
@Test
|
||||
public void getInstanceReturnsASingleInstance() {
|
||||
|
||||
SimpleCacheResolver cacheResolver = SimpleCacheResolver.getInstance();
|
||||
|
||||
assertThat(cacheResolver).isNotNull();
|
||||
assertThat(cacheResolver).isSameAs(SimpleCacheResolver.getInstance());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveWhenNoCacheIsPresentReturnsEmptyOptional() {
|
||||
assertThat(SimpleCacheResolver.getInstance().resolve().orElse(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveClientCacheWhenNoClientCacheIsPresentReturnsEmptyOptional() {
|
||||
assertThat(SimpleCacheResolver.getInstance().resolveClientCache().orElse(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvePeerCacheWhenNoPeerCacheIsPresentReturnsEmptyOptional() {
|
||||
assertThat(SimpleCacheResolver.getInstance().resolvePeerCache().orElse(null)).isNull();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void requireCacheWhenNoCacheIsPresentThrowsIllegalStateException() {
|
||||
|
||||
try {
|
||||
SimpleCacheResolver.getInstance().require();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("GemFireCache not found");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.cache;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.cache.client.ClientCacheFactory;
|
||||
|
||||
/**
|
||||
* Integration Tests for {@link SimpleCacheResolver} using an Apache Geode {@link ClientCache}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @see org.apache.geode.cache.client.ClientCacheFactory
|
||||
* @see org.springframework.geode.cache.SimpleCacheResolver
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class SimpleClientCacheResolverIntegrationTests {
|
||||
|
||||
private static ClientCache clientCache;
|
||||
|
||||
@BeforeClass
|
||||
public static void createClientCache() {
|
||||
clientCache = new ClientCacheFactory().create();
|
||||
assertThat(clientCache).isNotNull();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void destroyClientCache() {
|
||||
Optional.ofNullable(clientCache).ifPresent(ClientCache::close);
|
||||
clientCache = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveReturnsClientCache() {
|
||||
assertThat(SimpleCacheResolver.getInstance().resolve().orElse(null)).isSameAs(clientCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveClientCacheReturnsClientCache() {
|
||||
assertThat(SimpleCacheResolver.getInstance().resolveClientCache().orElse(null)).isSameAs(clientCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvePeerCacheReturnsEmptyOptional() {
|
||||
assertThat(SimpleCacheResolver.getInstance().resolvePeerCache().orElse(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requireReturnsClientCache() {
|
||||
assertThat(SimpleCacheResolver.getInstance().<ClientCache>require()).isSameAs(clientCache);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.cache;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.CacheFactory;
|
||||
|
||||
/**
|
||||
* Integration Tests for {@link SimpleCacheResolver} using an Apache Geode {@literal peer} {@link Cache}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.CacheFactory
|
||||
* @see org.springframework.geode.cache.SimpleCacheResolver
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class SimplePeerCacheResolverIntegrationTests {
|
||||
|
||||
private static Cache peerCache;
|
||||
|
||||
@BeforeClass
|
||||
public static void createPeerCache() {
|
||||
peerCache = new CacheFactory().create();
|
||||
assertThat(peerCache).isNotNull();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void destroyPeerCache() {
|
||||
Optional.ofNullable(peerCache).ifPresent(Cache::close);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveReturnsPeerCache() {
|
||||
assertThat(SimpleCacheResolver.getInstance().resolve().orElse(null)).isSameAs(peerCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveClientCacheReturnsEmptyOptional() {
|
||||
assertThat(SimpleCacheResolver.getInstance().resolveClientCache().orElse(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvePeerCacheReturnsPeerCache() {
|
||||
assertThat(SimpleCacheResolver.getInstance().resolvePeerCache().orElse(null)).isSameAs(peerCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requireReturnsPeerCache() {
|
||||
assertThat(SimpleCacheResolver.getInstance().<Cache>require()).isSameAs(peerCache);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.distributed.event;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.geode.distributed.DistributedMember;
|
||||
import org.apache.geode.distributed.internal.DistributionManager;
|
||||
import org.apache.geode.distributed.internal.InternalDistributedSystem;
|
||||
import org.apache.geode.internal.cache.InternalCache;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link MembershipEvent}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.apache.geode.distributed.internal.DistributionManager
|
||||
* @see org.springframework.geode.distributed.event.MembershipEvent
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class MembershipEventUnitTests {
|
||||
|
||||
@Test
|
||||
public void assertNotNullWithNonNullValue() {
|
||||
assertThat(MembershipEvent.assertNotNull("test", "message")).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void assertNotNullWithNullValue() {
|
||||
|
||||
try {
|
||||
MembershipEvent.assertNotNull(null, "Message with argument [%s]", "test");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Message with argument [test]");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructsNewMembershipEventWithDistributionManager() {
|
||||
|
||||
DistributionManager mockDistributionManager = mock(DistributionManager.class);
|
||||
|
||||
InternalCache mockCache = mock(InternalCache.class);
|
||||
|
||||
InternalDistributedSystem mockDistributedSystem = mock(InternalDistributedSystem.class);
|
||||
|
||||
doReturn(mockCache).when(mockDistributionManager).getCache();
|
||||
doReturn(mockDistributedSystem).when(mockDistributionManager).getSystem();
|
||||
|
||||
MembershipEvent<TestMembershipEvent> event = new TestMembershipEvent(mockDistributionManager);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getCache().orElse(null)).isEqualTo(mockCache);
|
||||
assertThat(event.getDistributedMember().orElse(null)).isNull();
|
||||
assertThat(event.getDistributedSystem().orElse(null)).isEqualTo(mockDistributedSystem);
|
||||
assertThat(event.getDistributionManager()).isEqualTo(mockDistributionManager);
|
||||
assertThat(event.getType()).isEqualTo(MembershipEvent.Type.UNQUALIFIED);
|
||||
|
||||
verify(mockDistributionManager, times(1)).getCache();
|
||||
verify(mockDistributionManager, times(1)).getSystem();
|
||||
verifyNoMoreInteractions(mockDistributionManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withMemberReturnsMember() {
|
||||
|
||||
DistributedMember mockDistributedMember = mock(DistributedMember.class);
|
||||
|
||||
DistributionManager mockDistributionManager = mock(DistributionManager.class);
|
||||
|
||||
MembershipEvent<TestMembershipEvent> event = new TestMembershipEvent(mockDistributionManager);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getDistributedMember().orElse(null)).isNull();
|
||||
assertThat(event.withMember(mockDistributedMember)).isSameAs(event);
|
||||
assertThat(event.getDistributedMember().orElse(null)).isEqualTo(mockDistributedMember);
|
||||
assertThat(event.withMember(null)).isSameAs(event);
|
||||
assertThat(event.getDistributedMember().orElse(null)).isNull();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructWithNullDistributionManagerThrowsIllegalArgumentException() {
|
||||
|
||||
try {
|
||||
new TestMembershipEvent(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("DistributionManager must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
static class TestMembershipEvent extends MembershipEvent<TestMembershipEvent> {
|
||||
|
||||
TestMembershipEvent(DistributionManager distributionManager) {
|
||||
super(distributionManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.distributed.event;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.distributed.DistributedSystem;
|
||||
import org.apache.geode.distributed.internal.DistributionManager;
|
||||
import org.apache.geode.distributed.internal.InternalDistributedSystem;
|
||||
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
|
||||
|
||||
import org.springframework.geode.distributed.event.support.MemberDepartedEvent;
|
||||
import org.springframework.geode.distributed.event.support.MemberJoinedEvent;
|
||||
import org.springframework.geode.distributed.event.support.MemberSuspectEvent;
|
||||
import org.springframework.geode.distributed.event.support.QuorumLostEvent;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link MembershipListenerAdapter}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see org.apache.geode.distributed.DistributedSystem
|
||||
* @see org.apache.geode.distributed.internal.DistributionManager
|
||||
* @see org.apache.geode.distributed.internal.membership.InternalDistributedMember
|
||||
* @see MembershipListenerAdapter
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MembershipListenerAdapterUnitTests {
|
||||
|
||||
@Mock
|
||||
private DistributionManager mockDistributionManager;
|
||||
|
||||
@Mock
|
||||
private InternalDistributedMember mockDistributedMember;
|
||||
|
||||
@Mock
|
||||
private InternalDistributedSystem mockDistributedSystem;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Set<T> asSet(T... elements) {
|
||||
return new HashSet<>(Arrays.asList(elements));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void memberDepartedCallsHandleMemberDeparted() {
|
||||
|
||||
MembershipListenerAdapter<?> listener = spy(new TestMembershipListener());
|
||||
|
||||
doAnswer(invocation -> {
|
||||
|
||||
MemberDepartedEvent event = invocation.getArgument(0);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.isCrashed()).isTrue();
|
||||
assertThat(event.getDistributedMember().orElse(null)).isEqualTo(this.mockDistributedMember);
|
||||
assertThat(event.getDistributionManager()).isEqualTo(this.mockDistributionManager);
|
||||
assertThat(event.getType()).isEqualTo(MembershipEvent.Type.MEMBER_DEPARTED);
|
||||
|
||||
return null;
|
||||
|
||||
}).when(listener).handleMemberDeparted(any(MemberDepartedEvent.class));
|
||||
|
||||
listener.memberDeparted(this.mockDistributionManager, this.mockDistributedMember, true);
|
||||
|
||||
verify(listener, times(1)).handleMemberDeparted(isA(MemberDepartedEvent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void memberJoinedCallsHandleMemberJoined() {
|
||||
|
||||
MembershipListenerAdapter<?> listener = spy(new TestMembershipListener());
|
||||
|
||||
doAnswer(invocation -> {
|
||||
|
||||
MemberJoinedEvent event = invocation.getArgument(0);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getDistributedMember().orElse(null)).isEqualTo(this.mockDistributedMember);
|
||||
assertThat(event.getDistributionManager()).isEqualTo(this.mockDistributionManager);
|
||||
assertThat(event.getType()).isEqualTo(MembershipEvent.Type.MEMBER_JOINED);
|
||||
|
||||
return null;
|
||||
|
||||
}).when(listener).handleMemberJoined(any(MemberJoinedEvent.class));
|
||||
|
||||
listener.memberJoined(this.mockDistributionManager, this.mockDistributedMember);
|
||||
|
||||
verify(listener, times(1)).handleMemberJoined(isA(MemberJoinedEvent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void memberSuspectCallsHandleMemberSuspect() {
|
||||
|
||||
InternalDistributedMember suspectMember = mock(InternalDistributedMember.class);
|
||||
|
||||
MembershipListenerAdapter<?> listener = spy(new TestMembershipListener());
|
||||
|
||||
doAnswer(invocation -> {
|
||||
|
||||
MemberSuspectEvent event = invocation.getArgument(0);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getDistributedMember().orElse(null)).isEqualTo(this.mockDistributedMember);
|
||||
assertThat(event.getDistributionManager()).isEqualTo(this.mockDistributionManager);
|
||||
assertThat(event.getReason().orElse(null)).isEqualTo("The system sucks!");
|
||||
assertThat(event.getSuspectMember().orElse(null)).isEqualTo(suspectMember);
|
||||
assertThat(event.getType()).isEqualTo(MembershipEvent.Type.MEMBER_SUSPECT);
|
||||
|
||||
return null;
|
||||
|
||||
}).when(listener).handleMemberSuspect(any(MemberSuspectEvent.class));
|
||||
|
||||
listener.memberSuspect(this.mockDistributionManager, this.mockDistributedMember, suspectMember,
|
||||
"The system sucks!");
|
||||
|
||||
verify(listener, times(1)).handleMemberSuspect(isA(MemberSuspectEvent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quorumLostCallsHandleQuorumLost() {
|
||||
|
||||
InternalDistributedMember mockMemberOne = mock(InternalDistributedMember.class);
|
||||
InternalDistributedMember mockMemberTwo = mock(InternalDistributedMember.class);
|
||||
|
||||
MembershipListenerAdapter<?> listener = spy(new TestMembershipListener());
|
||||
|
||||
doAnswer(invocation -> {
|
||||
|
||||
QuorumLostEvent event = invocation.getArgument(0);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getDistributedMember().orElse(null)).isNull();
|
||||
assertThat(event.getDistributionManager()).isEqualTo(this.mockDistributionManager);
|
||||
assertThat(event.getFailedMembers()).isEqualTo(asSet(mockMemberOne, mockMemberTwo));
|
||||
assertThat(event.getRemainingMembers()).isEqualTo(Collections.singletonList(this.mockDistributedMember));
|
||||
assertThat(event.getType()).isEqualTo(MembershipEvent.Type.QUORUM_LOST);
|
||||
|
||||
return null;
|
||||
|
||||
}).when(listener).handleQuorumLost(any(QuorumLostEvent.class));
|
||||
|
||||
listener.quorumLost(this.mockDistributionManager, asSet(mockMemberOne, mockMemberTwo),
|
||||
Collections.singletonList(this.mockDistributedMember));
|
||||
|
||||
verify(listener, times(1)).handleQuorumLost(isA(QuorumLostEvent.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registersListenerWithPeerCache() {
|
||||
|
||||
Cache mockCache = mock(Cache.class);
|
||||
|
||||
doReturn(this.mockDistributedSystem).when(mockCache).getDistributedSystem();
|
||||
doReturn(this.mockDistributionManager).when(this.mockDistributedSystem).getDistributionManager();
|
||||
|
||||
MembershipListenerAdapter<?> listener = new TestMembershipListener();
|
||||
|
||||
assertThat(listener.register(mockCache)).isSameAs(listener);
|
||||
|
||||
verify(mockCache, times(1)).getDistributedSystem();
|
||||
verify(this.mockDistributedSystem, times(1)).getDistributionManager();
|
||||
verify(this.mockDistributionManager, times(1))
|
||||
.addMembershipListener(eq(listener));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerListenerWithNullCacheIsNullSafe() {
|
||||
|
||||
MembershipListenerAdapter<?> listener = new TestMembershipListener();
|
||||
|
||||
assertThat(listener.register(null)).isSameAs(listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerListenerWithNullDistributedSystemIsNullSafe() {
|
||||
|
||||
Cache mockCache = mock(Cache.class);
|
||||
|
||||
MembershipListenerAdapter<?> listener = new TestMembershipListener();
|
||||
|
||||
assertThat(listener.register(mockCache)).isSameAs(listener);
|
||||
|
||||
verify(mockCache, times(1)).getDistributedSystem();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerListenerWithNonInternalDistributedSystemIsSafe() {
|
||||
|
||||
Cache mockCache = mock(Cache.class);
|
||||
|
||||
DistributedSystem mockDistributedSystem = mock(DistributedSystem.class);
|
||||
|
||||
doReturn(mockDistributedSystem).when(mockCache).getDistributedSystem();
|
||||
|
||||
MembershipListenerAdapter<?> listener = new TestMembershipListener();
|
||||
|
||||
assertThat(listener.register(mockCache)).isSameAs(listener);
|
||||
|
||||
verify(mockCache, times(1)).getDistributedSystem();
|
||||
verifyNoInteractions(mockDistributedSystem);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerListenerWithNullDistributionManagerIsNullSafe() {
|
||||
|
||||
Cache mockCache = mock(Cache.class);
|
||||
|
||||
doReturn(this.mockDistributedSystem).when(mockCache).getDistributedSystem();
|
||||
|
||||
MembershipListenerAdapter<?> listener = new TestMembershipListener();
|
||||
|
||||
assertThat(listener.register(mockCache)).isSameAs(listener);
|
||||
|
||||
verify(mockCache, times(1)).getDistributedSystem();
|
||||
verify(this.mockDistributedSystem, times(1)).getDistributionManager();
|
||||
}
|
||||
|
||||
static class TestMembershipListener extends MembershipListenerAdapter<TestMembershipListener> { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.distributed.event.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.geode.distributed.internal.DistributionManager;
|
||||
|
||||
import org.springframework.geode.distributed.event.MembershipEvent;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link MemberDepartedEvent}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.geode.distributed.event.MembershipEvent
|
||||
* @see org.springframework.geode.distributed.event.support.MemberDepartedEvent
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class MemberDepartedEventUnitTests {
|
||||
|
||||
@Test
|
||||
public void constructMemberDepartedEvent() {
|
||||
|
||||
DistributionManager mockDistributionManager = mock(DistributionManager.class);
|
||||
|
||||
MemberDepartedEvent event = new MemberDepartedEvent(mockDistributionManager);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getDistributionManager()).isEqualTo(mockDistributionManager);
|
||||
assertThat(event.isCrashed()).isFalse();
|
||||
assertThat(event.getType()).isEqualTo(MembershipEvent.Type.MEMBER_DEPARTED);
|
||||
|
||||
verifyNoInteractions(mockDistributionManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetCrashed() {
|
||||
|
||||
DistributionManager mockDistributionManager = mock(DistributionManager.class);
|
||||
|
||||
MemberDepartedEvent event = new MemberDepartedEvent(mockDistributionManager);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.isCrashed()).isFalse();
|
||||
assertThat(event.crashed(true)).isEqualTo(event);
|
||||
assertThat(event.isCrashed()).isTrue();
|
||||
assertThat(event.crashed(false)).isEqualTo(event);
|
||||
assertThat(event.isCrashed()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.distributed.event.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.geode.distributed.internal.DistributionManager;
|
||||
|
||||
import org.springframework.geode.distributed.event.MembershipEvent;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link MemberJoinedEvent}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.geode.distributed.event.MembershipEvent
|
||||
* @see org.springframework.geode.distributed.event.support.MemberJoinedEvent
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class MemberJoinedEventUnitTests {
|
||||
|
||||
@Test
|
||||
public void constructsMemberJoinedEvent() {
|
||||
|
||||
DistributionManager mockDistributionManager = mock(DistributionManager.class);
|
||||
|
||||
MemberJoinedEvent event = new MemberJoinedEvent(mockDistributionManager);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getDistributionManager()).isEqualTo(mockDistributionManager);
|
||||
assertThat(event.getType()).isEqualTo(MembershipEvent.Type.MEMBER_JOINED);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.distributed.event.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.geode.distributed.DistributedMember;
|
||||
import org.apache.geode.distributed.internal.DistributionManager;
|
||||
|
||||
import org.springframework.geode.distributed.event.MembershipEvent;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link MemberSuspectEvent}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see org.springframework.geode.distributed.event.MembershipEvent
|
||||
* @see org.springframework.geode.distributed.event.support.MemberSuspectEvent
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class MemberSuspectEventUnitTests {
|
||||
|
||||
@Test
|
||||
public void constructsMemberSuspectEvent() {
|
||||
|
||||
DistributionManager mockDistributionManager = mock(DistributionManager.class);
|
||||
|
||||
MemberSuspectEvent event = new MemberSuspectEvent(mockDistributionManager);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getDistributionManager()).isEqualTo(mockDistributionManager);
|
||||
assertThat(event.getReason().orElse(null)).isNull();
|
||||
assertThat(event.getSuspectMember().orElse(null)).isNull();
|
||||
assertThat(event.getType()).isEqualTo(MembershipEvent.Type.MEMBER_SUSPECT);
|
||||
|
||||
verifyNoInteractions(mockDistributionManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetReason() {
|
||||
|
||||
DistributionManager mockDistributionManager = mock(DistributionManager.class);
|
||||
|
||||
MemberSuspectEvent event = new MemberSuspectEvent(mockDistributionManager);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getReason().orElse(null)).isNull();
|
||||
assertThat(event.withReason("TEST")).isSameAs(event);
|
||||
assertThat(event.getReason().orElse(null)).isEqualTo("TEST");
|
||||
assertThat(event.withReason(null)).isSameAs(event);
|
||||
assertThat(event.getReason().orElse(null)).isNull();
|
||||
assertThat(event.withReason(" ")).isSameAs(event);
|
||||
assertThat(event.getReason().orElse(null)).isEqualTo(" ");
|
||||
assertThat(event.withReason(null)).isSameAs(event);
|
||||
assertThat(event.getReason().orElse(null)).isNull();
|
||||
assertThat(event.withReason("")).isSameAs(event);
|
||||
assertThat(event.getReason().orElse(null)).isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetSuspectMember() {
|
||||
|
||||
DistributedMember mockDistributedMember = mock(DistributedMember.class);
|
||||
|
||||
DistributionManager mockDistributionManager = mock(DistributionManager.class);
|
||||
|
||||
MemberSuspectEvent event = new MemberSuspectEvent(mockDistributionManager);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getSuspectMember().orElse(null)).isNull();
|
||||
assertThat(event.withSuspect(mockDistributedMember)).isSameAs(event);
|
||||
assertThat(event.getSuspectMember().orElse(null)).isEqualTo(mockDistributedMember);
|
||||
assertThat(event.withSuspect(null)).isSameAs(event);
|
||||
assertThat(event.getSuspectMember().orElse(null)).isNull();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.distributed.event.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.geode.distributed.DistributedMember;
|
||||
import org.apache.geode.distributed.internal.DistributionManager;
|
||||
|
||||
import org.springframework.geode.distributed.event.MembershipEvent;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link QuorumLostEvent}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.distributed.DistributedMember
|
||||
* @see org.springframework.geode.distributed.event.MembershipEvent
|
||||
* @see org.springframework.geode.distributed.event.support.QuorumLostEvent
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class QuorumLostEventUnitTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Iterable<T> normalize(Iterable<? extends T> iterable) {
|
||||
return (Iterable<T>) iterable;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructsQuorumLostEvent() {
|
||||
|
||||
DistributionManager mockDistributionManager = mock(DistributionManager.class);
|
||||
|
||||
QuorumLostEvent event = new QuorumLostEvent(mockDistributionManager);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getDistributionManager()).isEqualTo(mockDistributionManager);
|
||||
assertThat(event.getFailedMembers()).isEmpty();
|
||||
assertThat(event.getRemainingMembers()).isEmpty();
|
||||
assertThat(event.getType()).isEqualTo(MembershipEvent.Type.QUORUM_LOST);
|
||||
|
||||
verifyNoInteractions(mockDistributionManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetFailedMembers() {
|
||||
|
||||
DistributedMember mockMemberOne = mock(DistributedMember.class);
|
||||
DistributedMember mockMemberTwo = mock(DistributedMember.class);
|
||||
|
||||
DistributionManager mockDistributionManager = mock(DistributionManager.class);
|
||||
|
||||
QuorumLostEvent event = new QuorumLostEvent(mockDistributionManager);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getFailedMembers()).isNotNull();
|
||||
assertThat(event.getFailedMembers()).isEmpty();
|
||||
|
||||
assertThat(event.withFailedMembers(mockMemberOne, mockMemberTwo)).isSameAs(event);
|
||||
assertThat(this.<DistributedMember>normalize(event.getFailedMembers()))
|
||||
.containsExactlyInAnyOrder(mockMemberOne, mockMemberTwo);
|
||||
|
||||
assertThat(event.withFailedMembers((DistributedMember[]) null)).isSameAs(event);
|
||||
assertThat(event.getFailedMembers()).isNotNull();
|
||||
assertThat(event.getFailedMembers()).isEmpty();
|
||||
|
||||
assertThat(event.withFailedMembers(mockMemberOne)).isSameAs(event);
|
||||
assertThat(this.<DistributedMember>normalize(event.getFailedMembers())).containsExactly(mockMemberOne);
|
||||
|
||||
assertThat(event.withFailedMembers((Iterable<? extends DistributedMember>) null)).isSameAs(event);
|
||||
assertThat(event.getFailedMembers()).isNotNull();
|
||||
assertThat(event.getFailedMembers()).isEmpty();
|
||||
|
||||
assertThat(event.withFailedMembers(Collections.singleton(mockMemberTwo))).isSameAs(event);
|
||||
assertThat(this.<DistributedMember>normalize(event.getFailedMembers())).containsExactly(mockMemberTwo);
|
||||
|
||||
assertThat(event.withFailedMembers()).isSameAs(event);
|
||||
assertThat(event.getFailedMembers()).isNotNull();
|
||||
assertThat(event.getFailedMembers()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetRemainingMembers() {
|
||||
|
||||
DistributedMember mockMemberOne = mock(DistributedMember.class);
|
||||
DistributedMember mockMemberTwo = mock(DistributedMember.class);
|
||||
|
||||
DistributionManager mockDistributionManager = mock(DistributionManager.class);
|
||||
|
||||
QuorumLostEvent event = new QuorumLostEvent(mockDistributionManager);
|
||||
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getRemainingMembers()).isNotNull();
|
||||
assertThat(event.getRemainingMembers()).isEmpty();
|
||||
|
||||
assertThat(event.withRemainingMembers(mockMemberOne, mockMemberTwo)).isSameAs(event);
|
||||
assertThat(this.<DistributedMember>normalize(event.getRemainingMembers()))
|
||||
.containsExactlyInAnyOrder(mockMemberOne, mockMemberTwo);
|
||||
|
||||
assertThat(event.withRemainingMembers((DistributedMember[]) null)).isSameAs(event);
|
||||
assertThat(event.getRemainingMembers()).isNotNull();
|
||||
assertThat(event.getRemainingMembers()).isEmpty();
|
||||
|
||||
assertThat(event.withRemainingMembers(mockMemberOne)).isSameAs(event);
|
||||
assertThat(this.<DistributedMember>normalize(event.getRemainingMembers()))
|
||||
.containsExactlyInAnyOrder(mockMemberOne);
|
||||
|
||||
assertThat(event.withRemainingMembers((Iterable<? extends DistributedMember>) null)).isSameAs(event);
|
||||
assertThat(event.getRemainingMembers()).isNotNull();
|
||||
assertThat(event.getRemainingMembers()).isEmpty();
|
||||
|
||||
assertThat(event.withRemainingMembers(Collections.singletonList(mockMemberTwo))).isSameAs(event);
|
||||
assertThat(this.<DistributedMember>normalize(event.getRemainingMembers()))
|
||||
.containsExactlyInAnyOrder(mockMemberTwo);
|
||||
|
||||
assertThat(event.withRemainingMembers()).isSameAs(event);
|
||||
assertThat(event.getRemainingMembers()).isNotNull();
|
||||
assertThat(event.getRemainingMembers()).isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.pdx;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.RegionService;
|
||||
import org.apache.geode.pdx.PdxInstance;
|
||||
import org.apache.geode.pdx.PdxInstanceFactory;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link PdxInstanceBuilder}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.RegionService
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see org.apache.geode.pdx.PdxInstanceFactory
|
||||
* @see org.springframework.geode.pdx.PdxInstanceBuilder
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class PdxInstanceBuilderUnitTests {
|
||||
|
||||
@Test
|
||||
public void constructPdxInstanceBuilderInitializedWithRegionService() {
|
||||
|
||||
RegionService mockRegionService = mock(RegionService.class);
|
||||
|
||||
PdxInstanceBuilder builder = new PdxInstanceBuilder(mockRegionService);
|
||||
|
||||
assertThat(builder).isNotNull();
|
||||
assertThat(builder.getRegionService()).isEqualTo(mockRegionService);
|
||||
|
||||
verifyNoInteractions(mockRegionService);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructPdxInstanceBuilderWithNullRegionService() {
|
||||
|
||||
try {
|
||||
new PdxInstanceBuilder(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("RegionService must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createPdxInstanceBuilderWithRegionService() {
|
||||
|
||||
RegionService mockRegionService = mock(RegionService.class);
|
||||
|
||||
PdxInstanceBuilder builder = PdxInstanceBuilder.create(mockRegionService);
|
||||
|
||||
assertThat(builder).isNotNull();
|
||||
assertThat(builder.getRegionService()).isEqualTo(mockRegionService);
|
||||
|
||||
verifyNoMoreInteractions(mockRegionService);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void createPdxInstanceBuilderWithUnresolvableRegionService() {
|
||||
|
||||
try {
|
||||
PdxInstanceBuilder.create();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("GemFireCache not found");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyPdxInstance() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn("example.app.test.model.Type").when(mockPdxInstance).getClassName();
|
||||
doReturn("testOne").when(mockPdxInstance).getField(eq("fieldOne"));
|
||||
doReturn("testTwo").when(mockPdxInstance).getField(eq("fieldTwo"));
|
||||
doReturn(1).when(mockPdxInstance).getField(eq("id"));
|
||||
doReturn(Arrays.asList("fieldOne", "id", "fieldTwo")).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(true).when(mockPdxInstance).isIdentityField(eq("id"));
|
||||
|
||||
PdxInstanceFactory mockPdxInstanceFactory = mock(PdxInstanceFactory.class);
|
||||
|
||||
RegionService mockRegionService = mock(RegionService.class);
|
||||
|
||||
doReturn(mockPdxInstanceFactory).when(mockRegionService)
|
||||
.createPdxInstanceFactory(eq("example.app.test.model.Type"));
|
||||
|
||||
PdxInstanceBuilder builder = PdxInstanceBuilder.create(mockRegionService);
|
||||
|
||||
assertThat(builder).isNotNull();
|
||||
assertThat(builder.getRegionService()).isEqualTo(mockRegionService);
|
||||
assertThat(builder.copy(mockPdxInstance)).isEqualTo(mockPdxInstanceFactory);
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(mockPdxInstance, mockPdxInstanceFactory, mockRegionService);
|
||||
|
||||
inOrder.verify(mockPdxInstance, times(1)).getClassName();
|
||||
inOrder.verify(mockRegionService, times(1))
|
||||
.createPdxInstanceFactory(eq("example.app.test.model.Type"));
|
||||
inOrder.verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
inOrder.verify(mockPdxInstance, times(1)).getField(eq("fieldOne"));
|
||||
inOrder.verify(mockPdxInstanceFactory, times(1))
|
||||
.writeObject(eq("fieldOne"), eq("testOne"));
|
||||
inOrder.verify(mockPdxInstance, times(1)).isIdentityField(eq("fieldOne"));
|
||||
inOrder.verify(mockPdxInstance, times(1)).getField(eq("id"));
|
||||
inOrder.verify(mockPdxInstanceFactory, times(1))
|
||||
.writeObject(eq("id"), eq(1));
|
||||
inOrder.verify(mockPdxInstance, times(1)).isIdentityField(eq("id"));
|
||||
inOrder.verify(mockPdxInstanceFactory, times(1)).markIdentityField(eq("id"));
|
||||
inOrder.verify(mockPdxInstance, times(1)).getField(eq("fieldTwo"));
|
||||
inOrder.verify(mockPdxInstanceFactory, times(1))
|
||||
.writeObject(eq("fieldTwo"), eq("testTwo"));
|
||||
inOrder.verify(mockPdxInstance, times(1)).isIdentityField(eq("fieldTwo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyPdxInstanceWhenGetFieldsNamesReturnsNullIsNullSafe() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceFactory mockPdxInstanceFactory = mock(PdxInstanceFactory.class);
|
||||
|
||||
RegionService mockRegionService = mock(RegionService.class);
|
||||
|
||||
doReturn("example.app.test.model.Type").when(mockPdxInstance).getClassName();
|
||||
doReturn(null).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(mockPdxInstanceFactory).when(mockRegionService)
|
||||
.createPdxInstanceFactory(eq("example.app.test.model.Type"));
|
||||
|
||||
PdxInstanceBuilder builder = PdxInstanceBuilder.create(mockRegionService);
|
||||
|
||||
assertThat(builder).isNotNull();
|
||||
assertThat(builder.getRegionService()).isEqualTo(mockRegionService);
|
||||
assertThat(builder.copy(mockPdxInstance)).isEqualTo(mockPdxInstanceFactory);
|
||||
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verifyNoInteractions(mockPdxInstanceFactory);
|
||||
verify(mockRegionService, times(1))
|
||||
.createPdxInstanceFactory(eq("example.app.test.model.Type"));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void copyNullPdxInstanceThrowsIllegalArgumentException() {
|
||||
|
||||
RegionService mockRegionService = mock(RegionService.class);
|
||||
|
||||
try {
|
||||
PdxInstanceBuilder.create(mockRegionService).copy(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verifyNoInteractions(mockRegionService);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromSourceObject() {
|
||||
|
||||
Object source = new Object();
|
||||
|
||||
GemFireCache mockCache = mock(GemFireCache.class);
|
||||
|
||||
PdxInstance mockPdxInstanceHolder = mock(PdxInstance.class);
|
||||
PdxInstance mockPdxInstanceSource = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceFactory mockPdxInstanceFactory = mock(PdxInstanceFactory.class);
|
||||
|
||||
doReturn(true).when(mockCache).getPdxReadSerialized();
|
||||
doReturn(mockPdxInstanceFactory).when(mockCache).createPdxInstanceFactory(eq(source.getClass().getName()));
|
||||
doReturn(mockPdxInstanceHolder).when(mockPdxInstanceFactory).create();
|
||||
doReturn(mockPdxInstanceSource).when(mockPdxInstanceHolder).getField(eq("source"));
|
||||
|
||||
PdxInstanceBuilder builder = PdxInstanceBuilder.create(mockCache);
|
||||
|
||||
assertThat(builder).isNotNull();
|
||||
assertThat(builder.getRegionService()).isEqualTo(mockCache);
|
||||
|
||||
PdxInstanceBuilder.Factory factory = builder.from(source);
|
||||
|
||||
assertThat(factory).isNotNull();
|
||||
assertThat(factory.create()).isEqualTo(mockPdxInstanceSource);
|
||||
|
||||
verify(mockCache, times(1)).getPdxReadSerialized();
|
||||
verify(mockCache, times(1)).createPdxInstanceFactory(eq(source.getClass().getName()));
|
||||
verify(mockPdxInstanceFactory, times(1)).writeObject(eq("source"), eq(source));
|
||||
verify(mockPdxInstanceFactory, times(1)).create();
|
||||
verify(mockPdxInstanceHolder, times(1)).getField(eq("source"));
|
||||
verifyNoInteractions(mockPdxInstanceSource);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void fromNullSourceObjectThrowsIllegalArgumentException() {
|
||||
|
||||
RegionService mockRegionService = mock(RegionService.class);
|
||||
|
||||
try {
|
||||
PdxInstanceBuilder.create(mockRegionService).from(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Source object to serialize to PDX must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verifyNoInteractions(mockRegionService);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void fromNonNullSourceObjectWhenCacheIsNotPresent() {
|
||||
|
||||
RegionService mockRegionService = mock(RegionService.class);
|
||||
|
||||
try {
|
||||
PdxInstanceBuilder.create(mockRegionService).from("TEST");
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PDX read-serialized must be set to true");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verifyNoInteractions(mockRegionService);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void fromNonNullSourceObjectWhenCachePdxReadSerializedIsFalse() {
|
||||
|
||||
GemFireCache mockCache = mock(GemFireCache.class);
|
||||
|
||||
doReturn(false).when(mockCache).getPdxReadSerialized();
|
||||
|
||||
try {
|
||||
PdxInstanceBuilder.create(mockCache).from("TEST");
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PDX read-serialized must be set to true");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockCache, times(1)).getPdxReadSerialized();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void fromNonNullSourceObjectReturningNonPdxInstanceThrowsIllegalArgumentException() {
|
||||
|
||||
Object source = new Object();
|
||||
|
||||
GemFireCache mockCache = mock(GemFireCache.class);
|
||||
|
||||
PdxInstance mockPdxInstanceHolder = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceFactory mockPdxInstanceFactory = mock(PdxInstanceFactory.class);
|
||||
|
||||
doReturn(true).when(mockCache).getPdxReadSerialized();
|
||||
doReturn(mockPdxInstanceFactory).when(mockCache).createPdxInstanceFactory(eq(source.getClass().getName()));
|
||||
doReturn(mockPdxInstanceHolder).when(mockPdxInstanceFactory).create();
|
||||
doReturn(source).when(mockPdxInstanceHolder).getField(eq("source"));
|
||||
|
||||
PdxInstanceBuilder builder = PdxInstanceBuilder.create(mockCache);
|
||||
|
||||
assertThat(builder).isNotNull();
|
||||
assertThat(builder.getRegionService()).isEqualTo(mockCache);
|
||||
|
||||
PdxInstanceBuilder.Factory factory = builder.from(source);
|
||||
|
||||
assertThat(factory).isNotNull();
|
||||
|
||||
try {
|
||||
factory.create();
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Expected an instance of PDX but was an instance of type [%s];"
|
||||
+ " Was PDX read-serialized set to true", source.getClass().getName());
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockCache, times(1)).getPdxReadSerialized();
|
||||
verify(mockCache, times(1)).createPdxInstanceFactory(eq(source.getClass().getName()));
|
||||
verify(mockPdxInstanceFactory, times(1)).writeObject(eq("source"), eq(source));
|
||||
verify(mockPdxInstanceHolder, times(1)).getField(eq("source"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void fromNonNullSourceObjectReturningNullOnPdxInstanceFactoryCreateIsNullSafe() {
|
||||
|
||||
Object source = mock(Object.class);
|
||||
|
||||
GemFireCache mockCache = mock(GemFireCache.class);
|
||||
|
||||
PdxInstanceFactory mockPdxInstanceFactory = mock(PdxInstanceFactory.class);
|
||||
|
||||
doReturn(true).when(mockCache).getPdxReadSerialized();
|
||||
doReturn(mockPdxInstanceFactory).when(mockCache).createPdxInstanceFactory(eq(source.getClass().getName()));
|
||||
doReturn(null).when(mockPdxInstanceFactory).create();
|
||||
|
||||
PdxInstanceBuilder builder = PdxInstanceBuilder.create(mockCache);
|
||||
|
||||
assertThat(builder).isNotNull();
|
||||
assertThat(builder.getRegionService()).isEqualTo(mockCache);
|
||||
|
||||
PdxInstanceBuilder.Factory factory = builder.from(source);
|
||||
|
||||
assertThat(factory).isNotNull();
|
||||
|
||||
try {
|
||||
factory.create();
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Expected an instance of PDX but was an instance of type [null];"
|
||||
+ " Was PDX read-serialized set to true");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockCache, times(1)).getPdxReadSerialized();
|
||||
verify(mockCache, times(1)).createPdxInstanceFactory(eq(source.getClass().getName()));
|
||||
verify(mockPdxInstanceFactory, times(1)).writeObject(eq("source"), eq(source));
|
||||
verifyNoInteractions(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,813 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.pdx;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerationException;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.geode.internal.Sendable;
|
||||
import org.apache.geode.pdx.JSONFormatter;
|
||||
import org.apache.geode.pdx.PdxInstance;
|
||||
import org.apache.geode.pdx.WritablePdxInstance;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link PdxInstanceWrapper}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see com.fasterxml.jackson.core.JsonGenerator
|
||||
* @see com.fasterxml.jackson.databind.ObjectMapper
|
||||
* @see com.fasterxml.jackson.databind.json.JsonMapper
|
||||
* @see org.apache.geode.pdx.JSONFormatter
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see org.apache.geode.pdx.WritablePdxInstance
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class PdxInstanceWrapperUnitTests {
|
||||
|
||||
@Test
|
||||
public void constructPdxInstanceWrapper() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = new PdxInstanceWrapper(mockPdxInstance);
|
||||
|
||||
assertThat(wrapper).isNotNull();
|
||||
assertThat(wrapper.getDelegate()).isEqualTo(mockPdxInstance);
|
||||
|
||||
verifyNoInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructPdxInstanceWrapperWithNull() {
|
||||
|
||||
try {
|
||||
new PdxInstanceWrapper(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("Argument must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromObjectIsObject() {
|
||||
assertThat(PdxInstanceWrapper.from("TEST")).isEqualTo("TEST");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromNullIsNull() {
|
||||
assertThat(PdxInstanceWrapper.from((Object) null)).isEqualTo(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromPdxInstanceIsWrapper() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = PdxInstanceWrapper.from(mockPdxInstance);
|
||||
|
||||
assertThat(wrapper).isNotNull();
|
||||
assertThat(wrapper.getDelegate()).isEqualTo(mockPdxInstance);
|
||||
|
||||
verifyNoInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromPdxInstanceWrapperIsSameWrapper() {
|
||||
|
||||
PdxInstanceWrapper mockWrapper = mock(PdxInstanceWrapper.class);
|
||||
|
||||
assertThat(PdxInstanceWrapper.from(mockWrapper)).isSameAs(mockWrapper);
|
||||
|
||||
verifyNoInteractions(mockWrapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unwrapPdxInstanceWrapperReturnsPdxInstanceDelegate() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = PdxInstanceWrapper.from(mockPdxInstance);
|
||||
|
||||
assertThat(wrapper).isNotNull();
|
||||
assertThat(wrapper.getDelegate()).isEqualTo(mockPdxInstance);
|
||||
assertThat(PdxInstanceWrapper.unwrap(wrapper)).isEqualTo(mockPdxInstance);
|
||||
|
||||
verifyNoInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unwrapPdxInstanceReturnsPdxInstance() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
assertThat(PdxInstanceWrapper.unwrap(mockPdxInstance)).isEqualTo(mockPdxInstance);
|
||||
|
||||
verifyNoInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unwrapNullIsNullSafeAndReturnsNull() {
|
||||
assertThat(PdxInstanceWrapper.unwrap(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void objectMapperConfigurationIsCorrect() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(PdxInstanceWrapper.from(mockPdxInstance));
|
||||
|
||||
ObjectMapper mockObjectMapper = mock(ObjectMapper.class);
|
||||
|
||||
JsonMapper.Builder mockJsonMapperBuilder = mock(JsonMapper.Builder.class);
|
||||
|
||||
JsonMapper mockJsonMapper = mock(JsonMapper.class);
|
||||
|
||||
doReturn(mockJsonMapperBuilder).when(wrapper).newJsonMapperBuilder();
|
||||
doReturn(mockJsonMapperBuilder).when(mockJsonMapperBuilder).configure(any(DeserializationFeature.class), anyBoolean());
|
||||
doReturn(mockJsonMapperBuilder).when(mockJsonMapperBuilder).configure(any(MapperFeature.class), anyBoolean());
|
||||
doReturn(mockJsonMapper).when(mockJsonMapperBuilder).build();
|
||||
doReturn(mockObjectMapper).when(mockJsonMapper).findAndRegisterModules();
|
||||
|
||||
assertThat(wrapper.getDelegate()).isEqualTo(mockPdxInstance);
|
||||
|
||||
ObjectMapper objectMapper = wrapper.getObjectMapper().orElse(null);
|
||||
|
||||
assertThat(objectMapper).isNotNull();
|
||||
|
||||
verify(mockJsonMapperBuilder, times(1)).configure(eq(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES), eq(false));
|
||||
verify(mockJsonMapperBuilder, times(1)).configure(eq(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES), eq(false));
|
||||
verify(mockJsonMapperBuilder, times(1)).configure(eq(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS), eq(true));
|
||||
verify(mockJsonMapperBuilder, times(1)).build();
|
||||
verify(mockJsonMapper, times(1)).findAndRegisterModules();
|
||||
verifyNoMoreInteractions(mockJsonMapperBuilder, mockJsonMapper);
|
||||
verifyNoInteractions(mockPdxInstance, mockObjectMapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getClassNameCallsPdxInstanceGetClassName() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn("example.app.test.model.Type").when(mockPdxInstance).getClassName();
|
||||
|
||||
assertThat(PdxInstanceWrapper.from(mockPdxInstance).getClassName()).isEqualTo("example.app.test.model.Type");
|
||||
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isDeserializaleCallsPdxInstanceIsDeserializable() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(true).when(mockPdxInstance).isDeserializable();
|
||||
|
||||
assertThat(PdxInstanceWrapper.from(mockPdxInstance).isDeserializable()).isTrue();
|
||||
|
||||
verify(mockPdxInstance, times(1)).isDeserializable();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isEnumCallsPdxInstanceIsEnum() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(false).when(mockPdxInstance).isEnum();
|
||||
|
||||
assertThat(PdxInstanceWrapper.from(mockPdxInstance).isEnum()).isFalse();
|
||||
|
||||
verify(mockPdxInstance, times(1)).isEnum();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isIdentityFieldCallsPdxInstanceIsIdentityField() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(false).when(mockPdxInstance).isIdentityField(anyString());
|
||||
doReturn(true).when(mockPdxInstance).isIdentityField("id");
|
||||
|
||||
PdxInstanceWrapper wrapper = PdxInstanceWrapper.from(mockPdxInstance);
|
||||
|
||||
assertThat(wrapper.isIdentityField("id")).isTrue();
|
||||
assertThat(wrapper.isIdentityField("randomField")).isFalse();
|
||||
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("id"));
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("randomField"));
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFieldCallPdxInstanceGetField() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn("TestValue").when(mockPdxInstance).getField(eq("TestField"));
|
||||
|
||||
assertThat(PdxInstanceWrapper.from(mockPdxInstance).getField("TestField")).isEqualTo("TestValue");
|
||||
|
||||
verify(mockPdxInstance, times(1)).getField(eq("TestField"));
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFieldNameCallsPdxInstanceGetFieldNames() {
|
||||
|
||||
List<String> fieldNames = Arrays.asList("FieldOne", "FieldTwo");
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(fieldNames).when(mockPdxInstance).getFieldNames();
|
||||
|
||||
assertThat(PdxInstanceWrapper.from(mockPdxInstance).getFieldNames()).isEqualTo(fieldNames);
|
||||
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdentifierFromPdxInstanceHavingAnIdentity() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(Arrays.asList("age", "id", "name")).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(true).when(mockPdxInstance).isIdentityField(eq("id"));
|
||||
doReturn(42).when(mockPdxInstance).getField(eq("id"));
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
assertThat(wrapper.getIdentifier()).isEqualTo(42);
|
||||
|
||||
verify(wrapper, never()).getId();
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("age"));
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("id"));
|
||||
verify(mockPdxInstance, never()).isIdentityField(eq("name"));
|
||||
verify(mockPdxInstance, times(1)).getField(eq("id"));
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdentifierFromPdxInstanceHavingNoFields() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(null).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(69).when(wrapper).getId();
|
||||
|
||||
assertThat(wrapper.getIdentifier()).isEqualTo(69);
|
||||
|
||||
verify(wrapper, times(1)).getId();
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, never()).isIdentityField(anyString());
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdentifierFromPdxInstanceHavingNoIdentityFields() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(Arrays.asList("", "age", null, "name", " ")).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(false).when(mockPdxInstance).isIdentityField(any());
|
||||
doReturn(99).when(wrapper).getId();
|
||||
|
||||
assertThat(wrapper.getIdentifier()).isEqualTo(99);
|
||||
|
||||
verify(wrapper, times(1)).getId();
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("age"));
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("name"));
|
||||
verify(mockPdxInstance, never()).isIdentityField(isNull());
|
||||
verify(mockPdxInstance, never()).isIdentityField(eq(""));
|
||||
verify(mockPdxInstance, never()).isIdentityField(eq(" "));
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getIdentifierFromPdxInstanceWithNoIdentifier() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(Collections.singletonList("name")).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(false).when(mockPdxInstance).isIdentityField(anyString());
|
||||
doThrow(new IllegalStateException("NO ID")).when(wrapper).getId();
|
||||
|
||||
try {
|
||||
wrapper.getIdentifier();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("NO ID");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("name"));
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
verify(wrapper, times(1)).getId();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdFromPdxInstanceHavingIdField() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
doReturn(42).when(mockPdxInstance).getField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
|
||||
assertThat(wrapper.getId()).isEqualTo(42);
|
||||
|
||||
verify(mockPdxInstance, times(1)).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1)).getField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(wrapper, never()).getAtIdentifier();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdFromPdxInstanceHavingIdFieldWithNoValueReturnsNull() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
doReturn(null).when(mockPdxInstance).getField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
|
||||
assertThat(wrapper.getId()).isNull();
|
||||
|
||||
verify(mockPdxInstance, times(1)).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1)).getField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(wrapper, never()).getAtIdentifier();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdFromPdxInstanceWithNoIdFieldCallsGetAtIdentifier() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(false).when(mockPdxInstance).hasField(any());
|
||||
doReturn(99).when(wrapper).getAtIdentifier();
|
||||
|
||||
assertThat(wrapper.getId()).isEqualTo(99);
|
||||
|
||||
verify(mockPdxInstance, times(1)).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(wrapper, times(1)).getAtIdentifier();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAtIdentifierFromPdxInstance() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq("isbn"));
|
||||
doReturn("isbn").when(mockPdxInstance).getField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn("123456789").when(mockPdxInstance).getField(eq("isbn"));
|
||||
|
||||
assertThat(wrapper.getAtIdentifier()).isEqualTo("123456789");
|
||||
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.getField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1)).hasField(eq("isbn"));
|
||||
verify(mockPdxInstance, times(1)).getField(eq("isbn"));
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getAtIdentifierFromPdxInstanceWithNoDeclaredIdentity() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(Account.class.getName()).when(mockPdxInstance).getClassName();
|
||||
doReturn(false).when(mockPdxInstance).hasField(any());
|
||||
|
||||
try {
|
||||
wrapper.getAtIdentifier();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance for type [%s] has no declared identifier",
|
||||
Account.class.getName());
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(2))
|
||||
.hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getAtIdentifierFromPdxInstanceWithNoId() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(Account.class.getName()).when(mockPdxInstance).getClassName();
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
|
||||
try {
|
||||
wrapper.getAtIdentifier();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance for type [%s] has no id",
|
||||
Account.class.getName());
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(any());
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getAtIdentifierFromPdxInstanceWithValidAtIdentifierAndIdentifierFieldButNoId() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(Person.class.getName()).when(mockPdxInstance).getClassName();
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn(false).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq("ssn"));
|
||||
doReturn("ssn").when(mockPdxInstance).getField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn(null).when(mockPdxInstance).getField(eq("ssn"));
|
||||
|
||||
try {
|
||||
wrapper.getAtIdentifier();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
String expectedMessage = "PdxInstance for type [%s] has no value [null] for field [ssn] declared in [%s]";
|
||||
|
||||
assertThat(expected).hasMessage(expectedMessage, Person.class.getName(),
|
||||
PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME);
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(2)).hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1)).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(2)).hasField(eq("ssn"));
|
||||
verify(mockPdxInstance, times(2)).getField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(2)).getField(eq("ssn"));
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getAtIdentifierFromPdxInstanceWithAtIdentifierReferringToInvalidIdentifierField() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(Person.class.getName()).when(mockPdxInstance).getClassName();
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn(false).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
doReturn(false).when(mockPdxInstance).hasField(eq("ssn"));
|
||||
doReturn("ssn").when(mockPdxInstance).getField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
|
||||
try {
|
||||
wrapper.getAtIdentifier();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance for type [%s] has no field [ssn] declared in [%s]",
|
||||
Person.class.getName(), PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME);
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(2)).hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1)).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(2)).hasField(eq("ssn"));
|
||||
verify(mockPdxInstance, times(2)).getField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(eq("ssn"));
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectReturnsObject() throws JsonProcessingException {
|
||||
|
||||
Account mockAccount = mock(Account.class);
|
||||
|
||||
ObjectMapper mockObjectMapper = mock(ObjectMapper.class);
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
String json = String.format("{ \"@type\": \"%s\", \"name\": \"Savings\"}", Account.class.getName());
|
||||
|
||||
doReturn(JSONFormatter.JSON_CLASSNAME).when(mockPdxInstance).getClassName();
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.AT_TYPE_FIELD_NAME));
|
||||
doReturn(Account.class.getName()).when(mockPdxInstance).getField(eq(PdxInstanceWrapper.AT_TYPE_FIELD_NAME));
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(PdxInstanceWrapper.from(mockPdxInstance));
|
||||
|
||||
assertThat(wrapper).isNotNull();
|
||||
assertThat(wrapper.getDelegate()).isEqualTo(mockPdxInstance);
|
||||
|
||||
doReturn(Optional.of(mockObjectMapper)).when(wrapper).getObjectMapper();
|
||||
doReturn(json).when(wrapper).jsonFormatterToJson(eq(mockPdxInstance));
|
||||
doReturn(mockAccount).when(mockObjectMapper).readValue(eq(json), eq(Account.class));
|
||||
|
||||
assertThat(wrapper.getObject()).isEqualTo(mockAccount);
|
||||
|
||||
verify(wrapper, atLeastOnce()).getDelegate();
|
||||
verify(wrapper, times(1)).getObjectMapper();
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(1)).hasField(eq(PdxInstanceWrapper.AT_TYPE_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1)).getField(eq(PdxInstanceWrapper.AT_TYPE_FIELD_NAME));
|
||||
verify(wrapper, times(1)).jsonFormatterToJson(eq(mockPdxInstance));
|
||||
verify(mockObjectMapper, times(1)).readValue(eq(json), eq(Account.class));
|
||||
verify(mockPdxInstance, never()).getObject();
|
||||
verifyNoMoreInteractions(mockObjectMapper, mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getObjectCallsPdxInstanceGetObjectWhenAtTypeFieldIsNotPresent() throws JsonProcessingException {
|
||||
|
||||
Object value = new Object();
|
||||
|
||||
ObjectMapper mockObjectMapper = mock(ObjectMapper.class);
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(JSONFormatter.JSON_CLASSNAME).when(mockPdxInstance).getClassName();
|
||||
doReturn(false).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.AT_TYPE_FIELD_NAME));
|
||||
doReturn(value).when(mockPdxInstance).getObject();
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(PdxInstanceWrapper.from(mockPdxInstance));
|
||||
|
||||
assertThat(wrapper).isNotNull();
|
||||
assertThat(wrapper.getDelegate()).isEqualTo(mockPdxInstance);
|
||||
|
||||
doReturn(Optional.of(mockObjectMapper)).when(wrapper).getObjectMapper();
|
||||
|
||||
assertThat(wrapper.getObject()).isEqualTo(value);
|
||||
|
||||
verify(wrapper, atLeastOnce()).getDelegate();
|
||||
verify(wrapper, times(1)).getObjectMapper();
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(1)).hasField(eq(PdxInstanceWrapper.AT_TYPE_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
verify(wrapper, never()).jsonFormatterToJson(any());
|
||||
verify(mockObjectMapper, never()).readValue(anyString(), any(Class.class));
|
||||
verify(mockPdxInstance, times(1)).getObject();
|
||||
verifyNoMoreInteractions(mockObjectMapper, mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getObjectCallsPdxInstanceGetObjectWhenClassNameIsNotGemFireJson() throws JsonProcessingException {
|
||||
|
||||
ObjectMapper mockObjectMapper = mock(ObjectMapper.class);
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn("non.existing.class.Name").when(mockPdxInstance).getClassName();
|
||||
doReturn("TEST").when(mockPdxInstance).getObject();
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(PdxInstanceWrapper.from(mockPdxInstance));
|
||||
|
||||
assertThat(wrapper).isNotNull();
|
||||
assertThat(wrapper.getDelegate()).isEqualTo(mockPdxInstance);
|
||||
|
||||
doReturn(Optional.of(mockObjectMapper)).when(wrapper).getObjectMapper();
|
||||
|
||||
assertThat(wrapper.getObject()).isEqualTo("TEST");
|
||||
|
||||
verify(wrapper, atLeastOnce()).getDelegate();
|
||||
verify(wrapper, times(1)).getObjectMapper();
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, never()).hasField(anyString());
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
verify(wrapper, never()).jsonFormatterToJson(any());
|
||||
verify(mockObjectMapper, never()).readValue(anyString(), any(Class.class));
|
||||
verify(mockPdxInstance, times(1)).getObject();
|
||||
verifyNoMoreInteractions(mockObjectMapper, mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void getObjectCallsPdxInstanceGetObjectWhenExceptionIsThrown() throws JsonProcessingException {
|
||||
|
||||
Object value = new Object();
|
||||
|
||||
ObjectMapper mockObjectMapper = mock(ObjectMapper.class);
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
String json = String.format("{ \"@type\": \"%s\", \"name\": \"Checking\"}", Account.class.getName());
|
||||
|
||||
doReturn(JSONFormatter.JSON_CLASSNAME).when(mockPdxInstance).getClassName();
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.AT_TYPE_FIELD_NAME));
|
||||
doReturn(Account.class.getName()).when(mockPdxInstance).getField(eq(PdxInstanceWrapper.AT_TYPE_FIELD_NAME));
|
||||
doReturn(value).when(mockPdxInstance).getObject();
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(PdxInstanceWrapper.from(mockPdxInstance));
|
||||
|
||||
assertThat(wrapper).isNotNull();
|
||||
assertThat(wrapper.getDelegate()).isEqualTo(mockPdxInstance);
|
||||
|
||||
doReturn(Optional.of(mockObjectMapper)).when(wrapper).getObjectMapper();
|
||||
doReturn(json).when(wrapper).jsonFormatterToJson(eq(mockPdxInstance));
|
||||
doThrow(new JsonGenerationException("TEST", mock(JsonGenerator.class)))
|
||||
.when(mockObjectMapper).readValue(anyString(), any(Class.class));
|
||||
|
||||
assertThat(wrapper.getObject()).isEqualTo(value);
|
||||
|
||||
verify(wrapper, times(1)).getObjectMapper();
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(1)).hasField(eq(PdxInstanceWrapper.AT_TYPE_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1)).getField(eq(PdxInstanceWrapper.AT_TYPE_FIELD_NAME));
|
||||
verify(wrapper, atLeastOnce()).getDelegate();
|
||||
verify(wrapper, times(1)).jsonFormatterToJson(eq(mockPdxInstance));
|
||||
verify(mockObjectMapper, times(1)).readValue(eq(json), eq(Account.class));
|
||||
verify(mockPdxInstance, times((1))).getObject();
|
||||
verifyNoMoreInteractions(mockObjectMapper, mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectCallsPdxInstanceGetObjectWhenObjectMapperIsNotPresent() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn("non.existing.class.Name").when(mockPdxInstance).getClassName();
|
||||
doReturn("MOCK").when(mockPdxInstance).getObject();
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(PdxInstanceWrapper.from(mockPdxInstance));
|
||||
|
||||
assertThat(wrapper).isNotNull();
|
||||
assertThat(wrapper.getDelegate()).isEqualTo(mockPdxInstance);
|
||||
|
||||
doReturn(Optional.empty()).when(wrapper).getObjectMapper();
|
||||
|
||||
assertThat(wrapper.getObject()).isEqualTo("MOCK");
|
||||
|
||||
verify(wrapper, atLeastOnce()).getDelegate();
|
||||
verify(wrapper, times(1)).getObjectMapper();
|
||||
verify(wrapper, never()).jsonFormatterToJson(any());
|
||||
verify(mockPdxInstance, times(1)).getObject();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWriterCallsPdxInstanceCreateWriter() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
WritablePdxInstance mockWritablePdxInstance = mock(WritablePdxInstance.class);
|
||||
|
||||
doReturn(mockWritablePdxInstance).when(mockPdxInstance).createWriter();
|
||||
|
||||
assertThat(PdxInstanceWrapper.from(mockPdxInstance).createWriter()).isEqualTo(mockWritablePdxInstance);
|
||||
|
||||
verify(mockPdxInstance, times(1)).createWriter();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasFieldCallsPdxInstanceHasField() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(true).when(mockPdxInstance).hasField("name");
|
||||
|
||||
assertThat(PdxInstanceWrapper.from(mockPdxInstance).hasField("name")).isTrue();
|
||||
|
||||
verify(mockPdxInstance, times(1)).hasField(eq("name"));
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendToCallsPdxInstanceSendTo() throws IOException {
|
||||
|
||||
SendablePdxInstance mockSendablePdxInstance = mock(SendablePdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = PdxInstanceWrapper.from(mockSendablePdxInstance);
|
||||
|
||||
DataOutput mockOut = mock(DataOutput.class);
|
||||
|
||||
assertThat(wrapper).isNotNull();
|
||||
assertThat(wrapper.getDelegate()).isEqualTo(mockSendablePdxInstance);
|
||||
|
||||
wrapper.sendTo(mockOut);
|
||||
|
||||
verify(mockSendablePdxInstance, times(1)).sendTo(eq(mockOut));
|
||||
verifyNoMoreInteractions(mockSendablePdxInstance);
|
||||
verifyNoMoreInteractions(mockOut);
|
||||
}
|
||||
|
||||
interface Account {
|
||||
@SuppressWarnings("unused")
|
||||
String getName();
|
||||
}
|
||||
|
||||
interface Person { }
|
||||
|
||||
interface SendablePdxInstance extends PdxInstance, Sendable { }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.security;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.geode.util.GeodeConstants;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link TestAuthInitialize}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.Properties
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.geode.security.TestAuthInitialize
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TestAuthInitializeUnitTests {
|
||||
|
||||
private final TestAuthInitialize authInitialize = TestAuthInitialize.create();
|
||||
|
||||
private boolean isSet(String value) {
|
||||
return !(value == null || value.trim().isEmpty());
|
||||
}
|
||||
|
||||
private Properties newSecurityProperties(String username, String password) {
|
||||
|
||||
Properties securityProperties = new Properties();
|
||||
|
||||
if (isSet(username)) {
|
||||
securityProperties.setProperty(GeodeConstants.USERNAME, username);
|
||||
}
|
||||
|
||||
if (isSet(password)) {
|
||||
securityProperties.setProperty(GeodeConstants.PASSWORD, password);
|
||||
}
|
||||
|
||||
return securityProperties;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCredentialsUsesProperties() {
|
||||
|
||||
Properties securityProperties = newSecurityProperties("testUser", "s3cr3t");
|
||||
Properties credentials = this.authInitialize.getCredentials(securityProperties, null, false);
|
||||
|
||||
assertThat(credentials).isNotNull();
|
||||
assertThat(credentials.getProperty(GeodeConstants.USERNAME)).isEqualTo("testUser");
|
||||
assertThat(credentials.getProperty(GeodeConstants.PASSWORD)).isEqualTo("s3cr3t");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCredentialsUsesProvidedUsernameAndDefaultPassword() {
|
||||
|
||||
Properties securityProperties = newSecurityProperties("testUser", null);
|
||||
Properties credentials = this.authInitialize.getCredentials(securityProperties, null, false);
|
||||
|
||||
assertThat(credentials).isNotNull();
|
||||
assertThat(credentials.getProperty(GeodeConstants.USERNAME)).isEqualTo("testUser");
|
||||
assertThat(credentials.getProperty(GeodeConstants.PASSWORD)).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCredentialsUsesProvidedPasswordAndDefaultUsername() {
|
||||
|
||||
Properties securityProperties = newSecurityProperties(null, "s3cr3t");
|
||||
Properties credentials = this.authInitialize.getCredentials(securityProperties, null, false);
|
||||
|
||||
assertThat(credentials).isNotNull();
|
||||
assertThat(credentials.getProperty(GeodeConstants.USERNAME)).isEqualTo("test");
|
||||
assertThat(credentials.getProperty(GeodeConstants.PASSWORD)).isEqualTo("s3cr3t");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCredentialsUsesDefaultUsernameAndPassword() {
|
||||
|
||||
Properties securityProperties = newSecurityProperties(null, null);
|
||||
Properties credentials = this.authInitialize.getCredentials(securityProperties, null, false);
|
||||
|
||||
assertThat(credentials).isNotNull();
|
||||
assertThat(credentials.getProperty(GeodeConstants.USERNAME)).isEqualTo("test");
|
||||
assertThat(credentials.getProperty(GeodeConstants.PASSWORD)).isEqualTo("test");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.security;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.geode.security.AuthenticationFailedException;
|
||||
import org.apache.geode.security.ResourcePermission;
|
||||
|
||||
import org.springframework.geode.util.GeodeConstants;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link org.springframework.geode.security.TestSecurityManager}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.geode.security.TestSecurityManager
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TestSecurityManagerUnitTests {
|
||||
|
||||
private TestSecurityManager securityManager = new TestSecurityManager();
|
||||
|
||||
private Properties newSecurityProperties(String username, String password) {
|
||||
|
||||
Properties securityProperties = new Properties();
|
||||
|
||||
securityProperties.setProperty(GeodeConstants.USERNAME, username);
|
||||
securityProperties.setProperty(GeodeConstants.PASSWORD, password);
|
||||
|
||||
return securityProperties;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userAuthenticates() {
|
||||
|
||||
Object user = this.securityManager.authenticate(newSecurityProperties("test", "test"));
|
||||
|
||||
assertThat(user).isInstanceOf(TestSecurityManager.User.class);
|
||||
assertThat(((TestSecurityManager.User) user).getName()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test(expected = AuthenticationFailedException.class)
|
||||
public void userDoesNotAuthenticateBecauseUsernamePasswordAreCaseSensitive() {
|
||||
|
||||
try {
|
||||
this.securityManager.authenticate(newSecurityProperties("TestUser", "testuser"));
|
||||
}
|
||||
catch (AuthenticationFailedException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("User [TestUser] could not be authenticated");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = AuthenticationFailedException.class)
|
||||
public void userDoesNotAuthenticateWhenUsernamePasswordDoNotMatch() {
|
||||
|
||||
try {
|
||||
this.securityManager.authenticate(newSecurityProperties("testUser", "testPassword"));
|
||||
}
|
||||
catch (AuthenticationFailedException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("User [testUser] could not be authenticated");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userIsAlwaysAuthorized() {
|
||||
|
||||
ResourcePermission clusterManage =
|
||||
new ResourcePermission(ResourcePermission.Resource.CLUSTER, ResourcePermission.Operation.MANAGE);
|
||||
|
||||
assertThat(this.securityManager.authorize(null, clusterManage)).isTrue();
|
||||
assertThat(this.securityManager.authorize(new TestSecurityManager.User("test"), clusterManage)).isTrue();
|
||||
assertThat(this.securityManager.authorize(mock(Principal.class), clusterManage)).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,564 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.DataPolicy;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.RegionAttributes;
|
||||
import org.apache.geode.cache.RegionService;
|
||||
import org.apache.geode.cache.client.ClientCache;
|
||||
import org.apache.geode.internal.cache.GemFireCacheImpl;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link CacheUtils}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.RegionAttributes
|
||||
* @see org.apache.geode.cache.RegionService
|
||||
* @see org.apache.geode.cache.client.ClientCache
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class CacheUtilsUnitTests {
|
||||
|
||||
@Test
|
||||
public void collectValuesFromClientRegion() {
|
||||
|
||||
Region<Object, Object> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<Object, Object> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
RegionService mockRegionService = mock(ClientCache.class);
|
||||
|
||||
Set<?> keySetOnServer = new TreeSet<>(Arrays.asList(1, 2, 3));
|
||||
|
||||
Map<Object, Object> keysValues = new HashMap<>();
|
||||
|
||||
keysValues.put(1, "one");
|
||||
keysValues.put(2, "two");
|
||||
keysValues.put(3, "three");
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(mockRegionService).when(mockRegion).getRegionService();
|
||||
doReturn(keySetOnServer).when(mockRegion).keySetOnServer();
|
||||
doReturn(keysValues).when(mockRegion).getAll(eq(keySetOnServer));
|
||||
doReturn(DataPolicy.EMPTY).when(mockRegionAttributes).getDataPolicy();
|
||||
|
||||
assertThat(CacheUtils.collectValues(mockRegion)).containsExactlyInAnyOrder(keysValues.values().toArray());
|
||||
|
||||
verify(mockRegion, times(2)).getAttributes();
|
||||
verify(mockRegion, times(1)).getRegionService();
|
||||
verify(mockRegion, times(1)).keySetOnServer();
|
||||
verify(mockRegion, times(1)).getAll(eq(keySetOnServer));
|
||||
verify(mockRegion, never()).values();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, never()).getPoolName();
|
||||
verifyNoInteractions(mockRegionService);
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collectValuesFromClientRegionWhenClientRegionGetAllKeysReturnsNullMapIsNullSafe() {
|
||||
|
||||
Region<Object, Object> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<Object, Object> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
RegionService mockRegionService = mock(ClientCache.class);
|
||||
|
||||
Set<Object> keySetOnServer = new TreeSet<>(Arrays.asList(1, 2));
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(mockRegionService).when(mockRegion).getRegionService();
|
||||
doReturn(keySetOnServer).when(mockRegion).keySetOnServer();
|
||||
doReturn(null).when(mockRegion).getAll(eq(keySetOnServer));
|
||||
doReturn(DataPolicy.NORMAL).when(mockRegionAttributes).getDataPolicy();
|
||||
doReturn("Car").when(mockRegionAttributes).getPoolName();
|
||||
|
||||
Collection<Object> values = CacheUtils.collectValues(mockRegion);
|
||||
|
||||
assertThat(values).isNotNull();
|
||||
assertThat(values).isEmpty();
|
||||
|
||||
verify(mockRegion, times(3)).getAttributes();
|
||||
verify(mockRegion, times(1)).getRegionService();
|
||||
verify(mockRegion, times(1)).keySetOnServer();
|
||||
verify(mockRegion, times(1)).getAll(eq(keySetOnServer));
|
||||
verify(mockRegion, never()).values();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
verifyNoInteractions(mockRegionService);
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collectValuesFromClientRegionWhenClientRegionKeySetOnServerReturnsNullSetIsNullSafe() {
|
||||
|
||||
Region<Object, Object> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<Object, Object> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
RegionService mockRegionService = mock(ClientCache.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(mockRegionService).when(mockRegion).getRegionService();
|
||||
doReturn(null).when(mockRegion).keySetOnServer();
|
||||
doReturn(DataPolicy.PARTITION).when(mockRegionAttributes).getDataPolicy();
|
||||
doReturn("Dead").when(mockRegionAttributes).getPoolName();
|
||||
|
||||
Collection<Object> values = CacheUtils.collectValues(mockRegion);
|
||||
|
||||
assertThat(values).isNotNull();
|
||||
assertThat(values).isEmpty();
|
||||
|
||||
verify(mockRegion, times(3)).getAttributes();
|
||||
verify(mockRegion, times(1)).getRegionService();
|
||||
verify(mockRegion, times(1)).keySetOnServer();
|
||||
verify(mockRegion, never()).getAll(any());
|
||||
verify(mockRegion, never()).values();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
verifyNoInteractions(mockRegionService);
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collectValuesFromClientRegionWhenClientRegionGetRegionServiceReturnsNullIsNullSafe() {
|
||||
|
||||
Collection<Object> values = Arrays.asList("one", "two", "three");
|
||||
|
||||
Region<Object, Object> mockRegion = mock(Region.class);
|
||||
|
||||
doReturn(null).when(mockRegion).getRegionService();
|
||||
doReturn(values).when(mockRegion).values();
|
||||
|
||||
assertThat(CacheUtils.collectValues(mockRegion)).containsExactlyInAnyOrder(values.toArray());
|
||||
|
||||
verify(mockRegion, times(1)).getRegionService();
|
||||
verify(mockRegion, times(1)).values();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collectValuesFromLocalClientRegion() {
|
||||
|
||||
Region<?, String> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, String> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
RegionService mockRegionService = mock(ClientCache.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(mockRegionService).when(mockRegion).getRegionService();
|
||||
doReturn(DataPolicy.NORMAL).when(mockRegionAttributes).getDataPolicy();
|
||||
doReturn(" ").when(mockRegionAttributes).getPoolName();
|
||||
doReturn(Arrays.asList("one", "two")).when(mockRegion).values();
|
||||
|
||||
Collection<String> values = CacheUtils.collectValues(mockRegion);
|
||||
|
||||
assertThat(values).isNotNull();
|
||||
assertThat(values).containsExactly("one", "two");
|
||||
|
||||
verify(mockRegion, times(1)).getRegionService();
|
||||
verify(mockRegion, times(3)).getAttributes();
|
||||
verify(mockRegion, times(1)).values();
|
||||
verify(mockRegion, never()).keySetOnServer();
|
||||
verify(mockRegion, never()).getAll(any());
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
verifyNoInteractions(mockRegionService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void collectValuesFromPeerRegion() {
|
||||
|
||||
Region<Object, Object> mockRegion = mock(Region.class);
|
||||
|
||||
RegionService mockRegionService = mock(Cache.class);
|
||||
|
||||
Collection<Object> values = Arrays.asList("one", "two", "three");
|
||||
|
||||
doReturn(mockRegionService).when(mockRegion).getRegionService();
|
||||
doReturn(values).when(mockRegion).values();
|
||||
|
||||
assertThat(CacheUtils.collectValues(mockRegion)).containsExactlyInAnyOrder(values.toArray());
|
||||
|
||||
verify(mockRegion, times(1)).getRegionService();
|
||||
verify(mockRegion, times(1)).values();
|
||||
verifyNoInteractions(mockRegionService);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void collectValuesWithNullRegionThrowsIllegalArgumentException() {
|
||||
|
||||
try {
|
||||
CacheUtils.collectValues(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessageStartingWith("Argument must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isClientCacheWithClientCache() {
|
||||
assertThat(CacheUtils.isClientCache(mock(ClientCache.class))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isClientCacheWithGemFireCacheImplWhenIsClientReturnsTrue() {
|
||||
|
||||
GemFireCacheImpl mockCache = mock(GemFireCacheImpl.class);
|
||||
|
||||
doReturn(true).when(mockCache).isClient();
|
||||
|
||||
assertThat(CacheUtils.isClientCache(mockCache)).isTrue();
|
||||
|
||||
verify(mockCache, times(1)).isClient();
|
||||
verifyNoMoreInteractions(mockCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isClientCacheWithGemFireCacheImplWhenIsClientReturnsFalse() {
|
||||
|
||||
GemFireCacheImpl mockCache = mock(GemFireCacheImpl.class);
|
||||
|
||||
doReturn(false).when(mockCache).isClient();
|
||||
|
||||
assertThat(CacheUtils.isClientCache(mockCache)).isFalse();
|
||||
|
||||
verify(mockCache, times(1)).isClient();
|
||||
verifyNoMoreInteractions(mockCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isClientCacheWithNonClientCache() {
|
||||
assertThat(CacheUtils.isClientCache(mock(Cache.class))).isFalse();
|
||||
assertThat(CacheUtils.isClientCache(mock(GemFireCache.class))).isFalse();
|
||||
assertThat(CacheUtils.isClientCache(mock(RegionService.class))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isClientCacheWithNull() {
|
||||
assertThat(CacheUtils.isClientCache(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isClientRegionWithClientRegionInClientCache() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionService mockRegionService = mock(ClientCache.class);
|
||||
|
||||
doReturn(mockRegionService).when(mockRegion).getRegionService();
|
||||
|
||||
assertThat(CacheUtils.isClientRegion(mockRegion)).isTrue();
|
||||
assertThat(CacheUtils.isPeerRegion(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(2)).getRegionService();
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
verifyNoInteractions(mockRegionService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isClientRegionWithClientRegionDeterminedByPoolName() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, ?> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
RegionService mockRegionService = mock(RegionService.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(mockRegionService).when(mockRegion).getRegionService();
|
||||
doReturn("TestPool").when(mockRegionAttributes).getPoolName();
|
||||
|
||||
assertThat(CacheUtils.isClientRegion(mockRegion)).isTrue();
|
||||
assertThat(CacheUtils.isPeerRegion(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(2)).getRegionService();
|
||||
verify(mockRegion, times(2)).getAttributes();
|
||||
verify(mockRegionAttributes, times(2)).getPoolName();
|
||||
verifyNoMoreInteractions(mockRegion, mockRegionAttributes);
|
||||
verifyNoInteractions(mockRegionService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isClientRegionWithRegionHavingNoPoolName() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, ?> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(null).when(mockRegion).getRegionService();
|
||||
doReturn(" ").when(mockRegionAttributes).getPoolName();
|
||||
|
||||
assertThat(CacheUtils.isClientRegion(mockRegion)).isFalse();
|
||||
assertThat(CacheUtils.isPeerRegion(mockRegion)).isTrue();
|
||||
|
||||
verify(mockRegion, times(2)).getRegionService();
|
||||
verify(mockRegion, times(2)).getAttributes();
|
||||
verify(mockRegionAttributes, times(2)).getPoolName();
|
||||
verifyNoMoreInteractions(mockRegion, mockRegionAttributes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isClientRegionWithRegionHavingNoRegionAttributes() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
doReturn(null).when(mockRegion).getAttributes();
|
||||
doReturn(null).when(mockRegion).getRegionService();
|
||||
|
||||
assertThat(CacheUtils.isClientRegion(mockRegion)).isFalse();
|
||||
assertThat(CacheUtils.isPeerRegion(mockRegion)).isTrue();
|
||||
|
||||
verify(mockRegion, times(2)).getRegionService();
|
||||
verify(mockRegion, times(2)).getAttributes();
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isClientRegionWithPeerRegionInPeerCache() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionService mockRegionService = mock(Cache.class);
|
||||
|
||||
doReturn(mockRegionService).when(mockRegion).getRegionService();
|
||||
|
||||
assertThat(CacheUtils.isClientRegion(mockRegion)).isFalse();
|
||||
assertThat(CacheUtils.isPeerRegion(mockRegion)).isTrue();
|
||||
|
||||
verify(mockRegion, times(2)).getRegionService();
|
||||
verify(mockRegion, times(2)).getAttributes();
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isClientRegionWithNull() {
|
||||
assertThat(CacheUtils.isClientRegion(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isPeerCacheWithPeerCache() {
|
||||
assertThat(CacheUtils.isPeerCache(mock(Cache.class))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isPeerCacheWithGemFireCacheImplWhenIsClientReturnsTrue() {
|
||||
|
||||
GemFireCacheImpl mockCache = mock(GemFireCacheImpl.class);
|
||||
|
||||
doReturn(true).when(mockCache).isClient();
|
||||
|
||||
assertThat(CacheUtils.isPeerCache(mockCache)).isFalse();
|
||||
|
||||
verify(mockCache, times(1)).isClient();
|
||||
verifyNoMoreInteractions(mockCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isPeerCacheWithGemFireCacheImplWhenIsClientReturnsFalse() {
|
||||
|
||||
GemFireCacheImpl mockCache = mock(GemFireCacheImpl.class);
|
||||
|
||||
doReturn(false).when(mockCache).isClient();
|
||||
|
||||
assertThat(CacheUtils.isPeerCache(mockCache)).isTrue();
|
||||
|
||||
verify(mockCache, times(1)).isClient();
|
||||
verifyNoMoreInteractions(mockCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isPeerCacheWithNonPeerCache() {
|
||||
assertThat(CacheUtils.isPeerCache(mock(ClientCache.class))).isFalse();
|
||||
assertThat(CacheUtils.isPeerCache(mock(GemFireCache.class))).isFalse();
|
||||
assertThat(CacheUtils.isPeerCache(mock(RegionService.class))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isPeerCacheWithNull() {
|
||||
assertThat(CacheUtils.isPeerCache(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isPeerRegionWithNull() {
|
||||
assertThat(CacheUtils.isPeerRegion(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isProxyRegionWithProxyRegionBasedOnDataPolicy() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, ?> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(DataPolicy.EMPTY).when(mockRegionAttributes).getDataPolicy();
|
||||
|
||||
assertThat(CacheUtils.isProxyRegion(mockRegion)).isTrue();
|
||||
|
||||
verify(mockRegion, times(2)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, never()).getPoolName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isProxyRegionWithProxyRegionBasedOnPoolConfiguration() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, ?> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(DataPolicy.NORMAL).when(mockRegionAttributes).getDataPolicy();
|
||||
doReturn("TestPool").when(mockRegionAttributes).getPoolName();
|
||||
|
||||
assertThat(CacheUtils.isProxyRegion(mockRegion)).isTrue();
|
||||
|
||||
verify(mockRegion, times(3)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isProxyRegionWithNonProxyRegion() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, ?> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(DataPolicy.NORMAL).when(mockRegionAttributes).getDataPolicy();
|
||||
doReturn(" ").when(mockRegionAttributes).getPoolName();
|
||||
|
||||
assertThat(CacheUtils.isProxyRegion(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(3)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getDataPolicy();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isProxyRegionWithRegionHavingNoAttributesIsNullSafe() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
assertThat(CacheUtils.isProxyRegion(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isProxyRegionWithNullRegionIsNullSafe() {
|
||||
assertThat(CacheUtils.isProxyRegion(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRegionWithPoolWithPooledRegion() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, ?> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn("Swimming").when(mockRegionAttributes).getPoolName();
|
||||
|
||||
assertThat(CacheUtils.isRegionWithPool(mockRegion)).isTrue();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRegionWithPoolUsingRegionHavingNoAttributesIsNullSafe() {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
assertThat(CacheUtils.isRegionWithPool(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verifyNoMoreInteractions(mockRegion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRegionWithPoolUsingNullRegionIsNullSafe() {
|
||||
assertThat(CacheUtils.isRegionWithPool(null)).isFalse();
|
||||
}
|
||||
|
||||
private void testIsRegionWithPoolUsingRegionWithInvalidPoolNameReturnsFalse(String poolName) {
|
||||
|
||||
Region<?, ?> mockRegion = mock(Region.class);
|
||||
|
||||
RegionAttributes<?, ?> mockRegionAttributes = mock(RegionAttributes.class);
|
||||
|
||||
doReturn(mockRegionAttributes).when(mockRegion).getAttributes();
|
||||
doReturn(poolName).when(mockRegionAttributes).getPoolName();
|
||||
|
||||
assertThat(CacheUtils.isRegionWithPool(mockRegion)).isFalse();
|
||||
|
||||
verify(mockRegion, times(1)).getAttributes();
|
||||
verify(mockRegionAttributes, times(1)).getPoolName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRegionWithPoolUsingRegionConfiguredWithBlankPoolName() {
|
||||
testIsRegionWithPoolUsingRegionWithInvalidPoolNameReturnsFalse(" ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRegionWithPoolUsingRegionConfiguredWithEmptyPoolName() {
|
||||
testIsRegionWithPoolUsingRegionWithInvalidPoolNameReturnsFalse("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isRegionWithPoolUsingRegionConfiguredWithNullPoolName() {
|
||||
testIsRegionWithPoolUsingRegionWithInvalidPoolNameReturnsFalse(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.util.function;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link InvocationArguments).
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.geode.util.function.InvocationArguments
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class InvocationArgumentsUnitTests {
|
||||
|
||||
@Test
|
||||
public void constructsInvocationArgumentsWithArguments() {
|
||||
|
||||
Object[] arguments = { true, 'c', 1, Math.PI, "test" };
|
||||
|
||||
InvocationArguments invocationArguments = new InvocationArguments(arguments);
|
||||
|
||||
assertThat(invocationArguments).isNotNull();
|
||||
assertThat(invocationArguments.size()).isEqualTo(arguments.length);
|
||||
assertThat(Arrays.equals(invocationArguments.getArguments(), arguments)).isTrue();
|
||||
assertThat(invocationArguments.<Boolean>getArgumentAt(0)).isEqualTo(true);
|
||||
assertThat(invocationArguments.<Character>getArgumentAt(1)).isEqualTo('c');
|
||||
assertThat(invocationArguments.<Integer>getArgumentAt(2)).isEqualTo(1);
|
||||
assertThat(invocationArguments.<Double>getArgumentAt(3)).isEqualTo(Math.PI);
|
||||
assertThat(invocationArguments.<String>getArgumentAt(4)).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromConstructsNewInvocationArguments() {
|
||||
|
||||
InvocationArguments arguments = InvocationArguments.from("test", 1, false);
|
||||
|
||||
assertThat(arguments).isNotNull();
|
||||
assertThat(arguments).hasSize(3);
|
||||
assertThat(arguments.size()).isEqualTo(3);
|
||||
assertThat(arguments).containsExactly("test", 1, false);
|
||||
assertThat(arguments.<String>getArgumentAt(0)).isEqualTo("test");
|
||||
assertThat(arguments.<Integer>getArgumentAt(1)).isEqualTo(1);
|
||||
assertThat(arguments.<Boolean>getArgumentAt(2)).isEqualTo(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructInvocationArgumentsWithNull() {
|
||||
|
||||
InvocationArguments arguments = new InvocationArguments(null);
|
||||
|
||||
assertThat(arguments).isNotNull();
|
||||
assertThat(arguments).hasSize(0);
|
||||
assertThat(arguments.getArguments()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void iteratesArguments() {
|
||||
|
||||
Object[] arguments = { true, 1, "test" };
|
||||
|
||||
InvocationArguments invocationArguments = new InvocationArguments(arguments);
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (Object argument : invocationArguments) {
|
||||
assertThat(argument).isEqualTo(arguments[index++]);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringIsCorrect() {
|
||||
|
||||
InvocationArguments arguments = InvocationArguments.from("one", "two", "three");
|
||||
|
||||
assertThat(arguments).isNotNull();
|
||||
assertThat(arguments.toString()).isEqualTo("[one, two, three]");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.util.function;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doCallRealMethod;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link TriConsumer}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.geode.util.function.TriConsumer
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class TriConsumerUnitTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void andThenComposesTriConsumers() {
|
||||
|
||||
TriConsumer consumerOne = mock(TriConsumer.class);
|
||||
TriConsumer consumerTwo = mock(TriConsumer.class);
|
||||
|
||||
doCallRealMethod().when(consumerOne).andThen(any(TriConsumer.class));
|
||||
|
||||
TriConsumer composedConsumer = consumerOne.andThen(consumerTwo);
|
||||
|
||||
assertThat(composedConsumer).isNotNull();
|
||||
assertThat(composedConsumer).isNotSameAs(consumerOne);
|
||||
assertThat(composedConsumer).isNotSameAs(consumerTwo);
|
||||
|
||||
composedConsumer.accept("one", "two", "three");
|
||||
|
||||
InOrder order = inOrder(consumerOne, consumerTwo);
|
||||
|
||||
order.verify(consumerOne, times(1))
|
||||
.accept(eq("one"), eq("two"), eq("three"));
|
||||
order.verify(consumerTwo, times(1))
|
||||
.accept(eq("one"), eq("two"), eq("three"));
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void andThenWithNull() {
|
||||
|
||||
TriConsumer consumer = mock(TriConsumer.class);
|
||||
|
||||
doCallRealMethod().when(consumer).andThen(any());
|
||||
|
||||
consumer.andThen(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2017-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.util.function;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doCallRealMethod;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link TupleConsumer}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.function.Consumer
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.geode.util.function.TupleConsumer
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class TupleConsumerUnitTests {
|
||||
|
||||
@Test
|
||||
public void andThenComposesTupleConsumers() {
|
||||
|
||||
TupleConsumer consumerOne = mock(TupleConsumer.class);
|
||||
TupleConsumer consumerTwo = mock(TupleConsumer.class);
|
||||
|
||||
doCallRealMethod().when(consumerOne).andThen(any(TupleConsumer.class));
|
||||
|
||||
Consumer<InvocationArguments> composedConsumer = consumerOne.andThen(consumerTwo);
|
||||
|
||||
assertThat(composedConsumer).isNotNull();
|
||||
assertThat(composedConsumer).isNotSameAs(consumerOne);
|
||||
assertThat(composedConsumer).isNotSameAs(consumerTwo);
|
||||
|
||||
InvocationArguments arguments = InvocationArguments.from("test", 1, true);
|
||||
|
||||
composedConsumer.accept(arguments);
|
||||
|
||||
InOrder order = inOrder(consumerOne, consumerTwo);
|
||||
|
||||
order.verify(consumerOne, times(1)).accept(eq(arguments));
|
||||
order.verify(consumerTwo, times(1)).accept(eq(arguments));
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void andThenWithNull() {
|
||||
|
||||
TupleConsumer consumer = mock(TupleConsumer.class);
|
||||
|
||||
doCallRealMethod().when(consumer).andThen(any());
|
||||
|
||||
consumer.andThen(null);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user