Restructure the Spring Boot for Apache Geode project to mirror Spring Boot's project structure.

Resolves gh-60.
This commit is contained in:
John Blum
2022-02-24 16:23:35 -08:00
parent 0e8e3baeeb
commit 192133b95e
576 changed files with 0 additions and 19 deletions

View File

@@ -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;
}
}

View File

@@ -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"));
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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() { }
}

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -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());
}
}

View File

@@ -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);
};
}
}

View File

@@ -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> {
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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> { }
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}
}

View File

@@ -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 { }
}

View File

@@ -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");
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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]");
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}