This is an automated email from the ASF dual-hosted git repository. prhomberg pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/geode.git
commit 9636d670fc4cbdef2b614132d6c9721005db4731 Author: Patrick Rhomberg <[email protected]> AuthorDate: Tue Nov 28 16:19:19 2017 -0800 GEODE-3955: Add AEQ and Gateway Sender information to 'describe region' output. * Add DUnit test coverage for 'describe region' command * Add JUnit test coverage for RegionDescription class * Expansion and refactoring of touched classes. - This closes #1099. --- .../cli/commands/DescribeRegionCommand.java | 28 +- .../internal/cli/domain/RegionAttributesInfo.java | 283 +++++++++++---------- .../internal/cli/domain/RegionDescription.java | 44 ++-- .../internal/cli/result/CommandResult.java | 25 +- .../internal/cli/util/RegionAttributesNames.java | 2 + .../sanctioned-geode-core-serializables.txt | 4 +- .../cli/commands/DescribeRegionDUnitTest.java | 89 +++---- .../commands/DescribeRegionIntegrationTest.java | 16 +- .../cli/commands/DescribeRegionJUnitTest.java | 188 ++++++++++++++ .../cli/domain/RegionDescriptionJUnitTest.java | 255 +++++++++++++++++++ .../apache/geode/test/dunit/rules/MemberVM.java | 4 - .../test/junit/assertions/CommandResultAssert.java | 4 + .../cli/commands/DescribeRegionDUnitTest.java | 68 +++++ 13 files changed, 755 insertions(+), 255 deletions(-) diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeRegionCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeRegionCommand.java index 971f54e..0abe36a 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeRegionCommand.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeRegionCommand.java @@ -20,16 +20,17 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.logging.log4j.Logger; import org.springframework.shell.core.annotation.CliCommand; import org.springframework.shell.core.annotation.CliOption; import org.apache.geode.cache.execute.ResultCollector; import org.apache.geode.internal.cache.InternalCache; +import org.apache.geode.internal.logging.LogService; import org.apache.geode.management.cli.CliMetaData; import org.apache.geode.management.cli.ConverterHint; import org.apache.geode.management.cli.Result; import org.apache.geode.management.internal.cli.CliUtil; -import org.apache.geode.management.internal.cli.LogWrapper; import org.apache.geode.management.internal.cli.domain.FixedPartitionAttributesInfo; import org.apache.geode.management.internal.cli.domain.RegionDescription; import org.apache.geode.management.internal.cli.domain.RegionDescriptionPerMember; @@ -43,6 +44,8 @@ import org.apache.geode.management.internal.security.ResourceOperation; import org.apache.geode.security.ResourcePermission; public class DescribeRegionCommand implements GfshCommand { + public static final Logger logger = LogService.getLogger(); + private static final GetRegionDescriptionFunction getRegionDescription = new GetRegionDescriptionFunction(); @@ -54,15 +57,11 @@ public class DescribeRegionCommand implements GfshCommand { @CliOption(key = CliStrings.DESCRIBE_REGION__NAME, optionContext = ConverterHint.REGION_PATH, help = CliStrings.DESCRIBE_REGION__NAME__HELP, mandatory = true) String regionName) { - InternalCache cache = getCache(); - ResultCollector<?, ?> rc = - CliUtil.executeFunction(getRegionDescription, regionName, getAllNormalMembers(cache)); - - List<?> resultList = (List<?>) rc.getResult(); + List<?> resultList = getFunctionResultFromMembers(regionName); // Log any errors received. resultList.stream().filter(Throwable.class::isInstance).map(Throwable.class::cast) - .forEach(t -> LogWrapper.getInstance().info(t.getMessage(), t)); + .forEach(t -> logger.info(t.getMessage(), t)); // Aggregate PerMember data to to a single RegionDescription RegionDescription regionDescription = new RegionDescription(); @@ -83,6 +82,14 @@ public class DescribeRegionCommand implements GfshCommand { return buildDescriptionResult(regionName, regionDescription); } + List<?> getFunctionResultFromMembers(String regionName) { + InternalCache cache = getCache(); + ResultCollector<?, ?> rc = + executeFunction(getRegionDescription, regionName, getAllNormalMembers(cache)); + + return (List<?>) rc.getResult(); + } + public Result buildDescriptionResult(String regionName, RegionDescription regionDescription) { if (regionDescription.isEmpty()) { return ResultBuilder @@ -157,7 +164,8 @@ public class DescribeRegionCommand implements GfshCommand { List<FixedPartitionAttributesInfo> fpaList = regDescPerMem.getFixedPartitionAttributes(); - if (!ndRa.isEmpty() || !ndEa.isEmpty() || !ndPa.isEmpty() || fpaList != null) { + if (!ndRa.isEmpty() || !ndEa.isEmpty() || !ndPa.isEmpty() + || (fpaList != null && !fpaList.isEmpty())) { setHeader = true; boolean memberNameAdded; memberNameAdded = writeAttributesToTable(table, @@ -172,8 +180,8 @@ public class DescribeRegionCommand implements GfshCommand { } if (setHeader) { - table.setHeader(CliStrings.format( - CliStrings.DESCRIBE_REGION__NONDEFAULT__PERMEMBERATTRIBUTES__HEADER, memberType)); + table.setHeader(CliStrings + .format(CliStrings.DESCRIBE_REGION__NONDEFAULT__PERMEMBERATTRIBUTES__HEADER, memberType)); } return ResultBuilder.buildResult(crd); diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/RegionAttributesInfo.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/RegionAttributesInfo.java index 64201eb..faaa919 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/RegionAttributesInfo.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/RegionAttributesInfo.java @@ -18,8 +18,10 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.commons.lang.StringUtils; @@ -40,11 +42,8 @@ import org.apache.geode.management.internal.cli.util.RegionAttributesNames; public class RegionAttributesInfo implements Serializable { - /** - * - */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 336184564012988487L; private Scope scope = AbstractRegion.DEFAULT_SCOPE; private boolean cloningEnabled = false; @@ -70,6 +69,8 @@ public class RegionAttributesInfo implements Serializable { private String compressorClassName = null; + private Set<String> asyncEventQueueIDs = new HashSet<>(); + private Set<String> gatewaySenderIDs = new HashSet<>(); private PartitionAttributesInfo partitionAttributesInfo = null; private EvictionAttributesInfo evictionAttributesInfo = null; @@ -138,7 +139,8 @@ public class RegionAttributesInfo implements Serializable { regionIdleTimeoutAction = expAction.toString(); } - + asyncEventQueueIDs = ra.getAsyncEventQueueIds(); + gatewaySenderIDs = ra.getGatewaySenderIds(); // Collecting information about all the CacheListeners, CacheWriters, CacheLoaders CacheListener<?, ?>[] cacheListeners = ra.getCacheListeners(); @@ -258,6 +260,14 @@ public class RegionAttributesInfo implements Serializable { return initialCapacity; } + public Set<String> getAsyncEventQueueIDs() { + return asyncEventQueueIDs; + } + + public Set<String> getGatewaySenderIDs() { + return gatewaySenderIDs; + } + public float getLoadFactor() { return loadFactor; } @@ -323,175 +333,166 @@ public class RegionAttributesInfo implements Serializable { */ public Map<String, String> getNonDefaultAttributes() { - if (nonDefaultAttributes == null) { - nonDefaultAttributes = new HashMap<String, String>(); - - if (cloningEnabled != RegionAttributesDefault.CLONING_ENABLED) { - nonDefaultAttributes.put(RegionAttributesNames.CLONING_ENABLED, - Boolean.toString(cloningEnabled)); - } - - if (!StringUtils.equals(RegionAttributesDefault.COMPRESSOR_CLASS_NAME, compressorClassName)) { - nonDefaultAttributes.put(RegionAttributesNames.COMPRESSOR, compressorClassName); - } - - if (concurrencyChecksEnabled != RegionAttributesDefault.CONCURRENCY_CHECK_ENABLED) { - nonDefaultAttributes.put(RegionAttributesNames.CONCURRENCY_CHECK_ENABLED, - Boolean.toString(concurrencyChecksEnabled)); - } - - - if (concurrencyLevel != RegionAttributesDefault.CONCURRENCY_LEVEL) { - nonDefaultAttributes.put(RegionAttributesNames.CONCURRENCY_LEVEL, - Integer.toString(concurrencyLevel)); - } - - - if (!dataPolicy.equals(RegionAttributesDefault.DATA_POLICY)) { - nonDefaultAttributes.put(RegionAttributesNames.DATA_POLICY, dataPolicy.toString()); - } - - - if (diskStoreName != null && !diskStoreName.equals(RegionAttributesDefault.DISK_STORE_NAME)) { - nonDefaultAttributes.put(RegionAttributesNames.DISK_STORE_NAME, diskStoreName); - } - - - if (enableAsyncConflation != RegionAttributesDefault.ENABLE_ASYNC_CONFLATION) { - nonDefaultAttributes.put(RegionAttributesNames.ENABLE_ASYNC_CONFLATION, - Boolean.toString(enableAsyncConflation)); - } - - - - if (enableSubscriptionConflation != RegionAttributesDefault.ENABLE_SUBSCRIPTION_CONFLATION) { - nonDefaultAttributes.put(RegionAttributesNames.ENABLE_SUBSCRIPTION_CONFLATION, - Boolean.toString(enableSubscriptionConflation)); - } - - - if (entryIdleTimeout != RegionAttributesDefault.ENTRY_IDLE_TIMEOUT) { - nonDefaultAttributes.put(RegionAttributesNames.ENTRY_IDLE_TIMEOUT, - Integer.toString(entryIdleTimeout)); - } - - - if (ignoreJTA != RegionAttributesDefault.IGNORE_JTA) { - nonDefaultAttributes.put(RegionAttributesNames.IGNORE_JTA, Boolean.toString(ignoreJTA)); - } - + if (nonDefaultAttributes != null) { + return nonDefaultAttributes; + } - if (indexMaintenanceSynchronous != RegionAttributesDefault.INDEX_MAINTENANCE_SYNCHRONOUS) { - nonDefaultAttributes.put(RegionAttributesNames.INDEX_MAINTENANCE_SYNCHRONOUS, - Boolean.toString(indexMaintenanceSynchronous)); - } + nonDefaultAttributes = new HashMap<>(); + if (cloningEnabled != RegionAttributesDefault.CLONING_ENABLED) { + nonDefaultAttributes.put(RegionAttributesNames.CLONING_ENABLED, + Boolean.toString(cloningEnabled)); + } - if (initialCapacity != RegionAttributesDefault.INITIAL_CAPACITY) { - nonDefaultAttributes.put(RegionAttributesNames.INITIAL_CAPACITY, - Integer.toString(initialCapacity)); - } + if (!StringUtils.equals(RegionAttributesDefault.COMPRESSOR_CLASS_NAME, compressorClassName)) { + nonDefaultAttributes.put(RegionAttributesNames.COMPRESSOR, compressorClassName); + } + if (concurrencyChecksEnabled != RegionAttributesDefault.CONCURRENCY_CHECK_ENABLED) { + nonDefaultAttributes.put(RegionAttributesNames.CONCURRENCY_CHECK_ENABLED, + Boolean.toString(concurrencyChecksEnabled)); + } - if (loadFactor != RegionAttributesDefault.LOAD_FACTOR) { - nonDefaultAttributes.put(RegionAttributesNames.LOAD_FACTOR, Float.toString(loadFactor)); - } + if (concurrencyLevel != RegionAttributesDefault.CONCURRENCY_LEVEL) { + nonDefaultAttributes.put(RegionAttributesNames.CONCURRENCY_LEVEL, + Integer.toString(concurrencyLevel)); + } + if (!dataPolicy.equals(RegionAttributesDefault.DATA_POLICY)) { + nonDefaultAttributes.put(RegionAttributesNames.DATA_POLICY, dataPolicy.toString()); + } - if (multicastEnabled != RegionAttributesDefault.MULTICAST_ENABLED) { - nonDefaultAttributes.put(RegionAttributesNames.MULTICAST_ENABLED, - Boolean.toString(multicastEnabled)); - } + if (diskStoreName != null && !diskStoreName.equals(RegionAttributesDefault.DISK_STORE_NAME)) { + nonDefaultAttributes.put(RegionAttributesNames.DISK_STORE_NAME, diskStoreName); + } + if (enableAsyncConflation != RegionAttributesDefault.ENABLE_ASYNC_CONFLATION) { + nonDefaultAttributes.put(RegionAttributesNames.ENABLE_ASYNC_CONFLATION, + Boolean.toString(enableAsyncConflation)); + } - if (poolName != null && !poolName.equals(RegionAttributesDefault.POOL_NAME)) { - nonDefaultAttributes.put(RegionAttributesNames.POOL_NAME, poolName); - } + if (enableSubscriptionConflation != RegionAttributesDefault.ENABLE_SUBSCRIPTION_CONFLATION) { + nonDefaultAttributes.put(RegionAttributesNames.ENABLE_SUBSCRIPTION_CONFLATION, + Boolean.toString(enableSubscriptionConflation)); + } + if (entryIdleTimeout != RegionAttributesDefault.ENTRY_IDLE_TIMEOUT) { + nonDefaultAttributes.put(RegionAttributesNames.ENTRY_IDLE_TIMEOUT, + Integer.toString(entryIdleTimeout)); + } - if (!scope.equals(RegionAttributesDefault.SCOPE)) { - nonDefaultAttributes.put(RegionAttributesNames.SCOPE, scope.toString()); - } + if (ignoreJTA != RegionAttributesDefault.IGNORE_JTA) { + nonDefaultAttributes.put(RegionAttributesNames.IGNORE_JTA, Boolean.toString(ignoreJTA)); + } + if (indexMaintenanceSynchronous != RegionAttributesDefault.INDEX_MAINTENANCE_SYNCHRONOUS) { + nonDefaultAttributes.put(RegionAttributesNames.INDEX_MAINTENANCE_SYNCHRONOUS, + Boolean.toString(indexMaintenanceSynchronous)); + } - if (statisticsEnabled != RegionAttributesDefault.STATISTICS_ENABLED) { - nonDefaultAttributes.put(RegionAttributesNames.STATISTICS_ENABLED, - Boolean.toString(statisticsEnabled)); - } + if (initialCapacity != RegionAttributesDefault.INITIAL_CAPACITY) { + nonDefaultAttributes.put(RegionAttributesNames.INITIAL_CAPACITY, + Integer.toString(initialCapacity)); + } + if (loadFactor != RegionAttributesDefault.LOAD_FACTOR) { + nonDefaultAttributes.put(RegionAttributesNames.LOAD_FACTOR, Float.toString(loadFactor)); + } + if (multicastEnabled != RegionAttributesDefault.MULTICAST_ENABLED) { + nonDefaultAttributes.put(RegionAttributesNames.MULTICAST_ENABLED, + Boolean.toString(multicastEnabled)); + } - if (isLockGrantor != RegionAttributesDefault.IS_LOCK_GRANTOR) { - nonDefaultAttributes.put(RegionAttributesNames.IS_LOCK_GRANTOR, - Boolean.toString(isLockGrantor)); - } + if (poolName != null && !poolName.equals(RegionAttributesDefault.POOL_NAME)) { + nonDefaultAttributes.put(RegionAttributesNames.POOL_NAME, poolName); + } + if (!scope.equals(RegionAttributesDefault.SCOPE)) { + nonDefaultAttributes.put(RegionAttributesNames.SCOPE, scope.toString()); + } - if (entryIdleTimeout != RegionAttributesDefault.ENTRY_IDLE_TIMEOUT) { - nonDefaultAttributes.put(RegionAttributesNames.ENTRY_IDLE_TIMEOUT, - Integer.toString(entryIdleTimeout)); - } + if (statisticsEnabled != RegionAttributesDefault.STATISTICS_ENABLED) { + nonDefaultAttributes.put(RegionAttributesNames.STATISTICS_ENABLED, + Boolean.toString(statisticsEnabled)); + } - if (entryIdleTimeoutAction != null - && !entryIdleTimeoutAction.equals(RegionAttributesDefault.ENTRY_IDLE_TIMEOUT_ACTION)) { - nonDefaultAttributes.put(RegionAttributesNames.ENTRY_IDLE_TIMEOUT_ACTION, - entryIdleTimeoutAction); - } + if (isLockGrantor != RegionAttributesDefault.IS_LOCK_GRANTOR) { + nonDefaultAttributes.put(RegionAttributesNames.IS_LOCK_GRANTOR, + Boolean.toString(isLockGrantor)); + } + if (entryIdleTimeout != RegionAttributesDefault.ENTRY_IDLE_TIMEOUT) { + nonDefaultAttributes.put(RegionAttributesNames.ENTRY_IDLE_TIMEOUT, + Integer.toString(entryIdleTimeout)); + } - if (entryTimeToLive != RegionAttributesDefault.ENTRY_TIME_TO_LIVE) { - nonDefaultAttributes.put(RegionAttributesNames.ENTRY_TIME_TO_LIVE, - Integer.toString(entryTimeToLive)); - } + if (entryIdleTimeoutAction != null + && !entryIdleTimeoutAction.equals(RegionAttributesDefault.ENTRY_IDLE_TIMEOUT_ACTION)) { + nonDefaultAttributes.put(RegionAttributesNames.ENTRY_IDLE_TIMEOUT_ACTION, + entryIdleTimeoutAction); + } + if (entryTimeToLive != RegionAttributesDefault.ENTRY_TIME_TO_LIVE) { + nonDefaultAttributes.put(RegionAttributesNames.ENTRY_TIME_TO_LIVE, + Integer.toString(entryTimeToLive)); + } - if (entryTimeToLiveAction != null - && !entryTimeToLiveAction.equals(RegionAttributesDefault.ENTRY_TIME_TO_LIVE_ACTION)) { - nonDefaultAttributes.put(RegionAttributesNames.ENTRY_TIME_TO_LIVE_ACTION, - entryTimeToLiveAction); - } + if (entryTimeToLiveAction != null + && !entryTimeToLiveAction.equals(RegionAttributesDefault.ENTRY_TIME_TO_LIVE_ACTION)) { + nonDefaultAttributes.put(RegionAttributesNames.ENTRY_TIME_TO_LIVE_ACTION, + entryTimeToLiveAction); + } + if (regionIdleTimeout != RegionAttributesDefault.REGION_IDLE_TIMEOUT) { + nonDefaultAttributes.put(RegionAttributesNames.REGION_IDLE_TIMEOUT, + Integer.toString(regionIdleTimeout)); + } - if (regionIdleTimeout != RegionAttributesDefault.REGION_IDLE_TIMEOUT) { - nonDefaultAttributes.put(RegionAttributesNames.REGION_IDLE_TIMEOUT, - Integer.toString(regionIdleTimeout)); - } + if (regionIdleTimeoutAction != null + && !regionIdleTimeoutAction.equals(RegionAttributesDefault.REGION_IDLE_TIMEOUT_ACTION)) { + nonDefaultAttributes.put(RegionAttributesNames.REGION_IDLE_TIMEOUT_ACTION, + regionIdleTimeoutAction); + } - if (regionIdleTimeoutAction != null - && !regionIdleTimeoutAction.equals(RegionAttributesDefault.REGION_IDLE_TIMEOUT_ACTION)) { - nonDefaultAttributes.put(RegionAttributesNames.REGION_IDLE_TIMEOUT_ACTION, - regionIdleTimeoutAction); - } + if (regionTimeToLive != RegionAttributesDefault.REGION_TIME_TO_LIVE) { + nonDefaultAttributes.put(RegionAttributesNames.REGION_TIME_TO_LIVE, + Integer.toString(regionTimeToLive)); + } - if (regionTimeToLive != RegionAttributesDefault.REGION_TIME_TO_LIVE) { - nonDefaultAttributes.put(RegionAttributesNames.REGION_TIME_TO_LIVE, - Integer.toString(regionTimeToLive)); - } + if (regionTimeToLiveAction != null + && !regionTimeToLiveAction.equals(RegionAttributesDefault.REGION_TIME_TO_LIVE_ACTION)) { + nonDefaultAttributes.put(RegionAttributesNames.REGION_TIME_TO_LIVE_ACTION, + regionTimeToLiveAction); + } + if (cacheListenerClassNames != null && !cacheListenerClassNames.isEmpty()) { + nonDefaultAttributes.put(RegionAttributesNames.CACHE_LISTENERS, + CliUtil.convertStringListToString(cacheListenerClassNames, ',')); + } - if (regionTimeToLiveAction != null - && !regionTimeToLiveAction.equals(RegionAttributesDefault.REGION_TIME_TO_LIVE_ACTION)) { - nonDefaultAttributes.put(RegionAttributesNames.REGION_TIME_TO_LIVE_ACTION, - regionTimeToLiveAction); - } + if (cacheLoaderClassName != null && !cacheLoaderClassName.isEmpty()) { + nonDefaultAttributes.put(RegionAttributesNames.CACHE_LOADER, cacheLoaderClassName); + } - if (cacheListenerClassNames != null && !cacheListenerClassNames.isEmpty()) { - nonDefaultAttributes.put(RegionAttributesNames.CACHE_LISTENERS, - CliUtil.convertStringListToString(cacheListenerClassNames, ',')); - } + if (cacheWriterClassName != null && !cacheWriterClassName.isEmpty()) { + nonDefaultAttributes.put(RegionAttributesNames.CACHE_WRITER, cacheWriterClassName); + } - if (cacheLoaderClassName != null && !cacheLoaderClassName.isEmpty()) { - nonDefaultAttributes.put(RegionAttributesNames.CACHE_LOADER, cacheLoaderClassName); - } + if (offHeap != RegionAttributesDefault.OFF_HEAP) { + nonDefaultAttributes.put(RegionAttributesNames.OFF_HEAP, Boolean.toString(offHeap)); + } - if (cacheWriterClassName != null && !cacheWriterClassName.isEmpty()) { - nonDefaultAttributes.put(RegionAttributesNames.CACHE_WRITER, cacheWriterClassName); - } + if (!asyncEventQueueIDs.isEmpty()) { + nonDefaultAttributes.put(RegionAttributesNames.ASYNC_EVENT_QUEUE_ID, + String.join(",", asyncEventQueueIDs)); + } - if (this.offHeap != RegionAttributesDefault.OFF_HEAP) { - nonDefaultAttributes.put(RegionAttributesNames.OFF_HEAP, Boolean.toString(this.offHeap)); - } + if (!gatewaySenderIDs.isEmpty()) { + nonDefaultAttributes.put(RegionAttributesNames.GATEWAY_SENDER_ID, + String.join(",", gatewaySenderIDs)); } - return this.nonDefaultAttributes; + + return nonDefaultAttributes; } } diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/RegionDescription.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/RegionDescription.java index 9f829b7..2f25afc 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/RegionDescription.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/RegionDescription.java @@ -29,7 +29,7 @@ import org.apache.geode.cache.Scope; */ public class RegionDescription implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 6461449275798378332L; private String name; private boolean isPartition; private boolean isPersistent; @@ -37,11 +37,11 @@ public class RegionDescription implements Serializable { private boolean isLocal = false; private boolean isAccessor = false; - + // COPY // Common Non Default Attributes - private Map<String, String> cndRegionAttributes; - private Map<String, String> cndPartitionAttributes; - private Map<String, String> cndEvictionAttributes; + private Map<String, String> cndRegionAttributes = new HashMap<>(); + private Map<String, String> cndPartitionAttributes = new HashMap<>(); + private Map<String, String> cndEvictionAttributes = new HashMap<>(); private Map<String, RegionDescriptionPerMember> regionDescPerMemberMap = null; private Scope scope; @@ -68,29 +68,23 @@ public class RegionDescription implements Serializable { if (regionDescPerMemberMap == null) { regionDescPerMemberMap = new HashMap<>(); regionDescPerMemberMap.put(regionDescPerMember.getHostingMember(), regionDescPerMember); - this.scope = regionDescPerMember.getScope(); - this.dataPolicy = regionDescPerMember.getDataPolicy(); - this.name = regionDescPerMember.getName(); - isPartition = this.dataPolicy.withPartitioning(); - isPersistent = this.dataPolicy.withPersistence(); - isReplicate = this.dataPolicy.withReplication(); - isLocal = this.scope.isLocal(); + scope = regionDescPerMember.getScope(); + dataPolicy = regionDescPerMember.getDataPolicy(); + name = regionDescPerMember.getName(); + isPartition = dataPolicy.withPartitioning(); + isPersistent = dataPolicy.withPersistence(); + isReplicate = dataPolicy.withReplication(); + isLocal = scope.isLocal(); isAccessor = regionDescPerMember.isAccessor(); - // COPY - this.cndRegionAttributes = new HashMap<>(); - this.cndRegionAttributes.putAll(regionDescPerMember.getNonDefaultRegionAttributes()); - - this.cndPartitionAttributes = new HashMap<>(); - this.cndPartitionAttributes.putAll(regionDescPerMember.getNonDefaultPartitionAttributes()); - - this.cndEvictionAttributes = new HashMap<>(); - this.cndEvictionAttributes.putAll(regionDescPerMember.getNonDefaultEvictionAttributes()); + cndRegionAttributes.putAll(regionDescPerMember.getNonDefaultRegionAttributes()); + cndPartitionAttributes.putAll(regionDescPerMember.getNonDefaultPartitionAttributes()); + cndEvictionAttributes.putAll(regionDescPerMember.getNonDefaultEvictionAttributes()); isAdded = true; - } else if (this.scope.equals(regionDescPerMember.getScope()) - && this.name.equals(regionDescPerMember.getName()) - && this.dataPolicy.equals(regionDescPerMember.getDataPolicy()) - && this.isAccessor == regionDescPerMember.isAccessor()) { + } else if (scope.equals(regionDescPerMember.getScope()) + && name.equals(regionDescPerMember.getName()) + && dataPolicy.equals(regionDescPerMember.getDataPolicy()) + && isAccessor == regionDescPerMember.isAccessor()) { regionDescPerMemberMap.put(regionDescPerMember.getHostingMember(), regionDescPerMember); findCommon(cndRegionAttributes, regionDescPerMember.getNonDefaultRegionAttributes()); diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/CommandResult.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/CommandResult.java index 13153ec..b7aac06 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/CommandResult.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/CommandResult.java @@ -618,15 +618,28 @@ public class CommandResult implements Result { return getTableContent(0, 0); } - public GfJsonObject getTableContent(int sectionIdx, int tableIdx) { + /** + * Most frequently, only two index values are required: a section index followed by a table index. + * Some commands, such as 'describe region', may return command results with subsections, however. + * Include these in order, e.g., getTableContent(sectionIndex, subsectionIndex, tableIndex); + */ + public GfJsonObject getTableContent(int... sectionAndTableIDs) { GfJsonObject topLevelContent = getContent(); - GfJsonObject sectionObject = topLevelContent.getJSONObject("__sections__-" + sectionIdx); - // This means we're just dealing with a regular ResultData object - if (sectionObject == null) { - return topLevelContent; + // Most common is receiving exactly one section index and one table index. + // Some results, however, will have subsections before the table listings. + assert (sectionAndTableIDs.length >= 2); + + GfJsonObject sectionObject = topLevelContent; + for (int i = 0; i < sectionAndTableIDs.length - 1; i++) { + int idx = sectionAndTableIDs[i]; + sectionObject = sectionObject.getJSONObject("__sections__-" + idx); + if (sectionObject == null) { + return topLevelContent; + } } - GfJsonObject tableContent = sectionObject.getJSONObject("__tables__-" + tableIdx); + int tableId = sectionAndTableIDs[sectionAndTableIDs.length - 1]; + GfJsonObject tableContent = sectionObject.getJSONObject("__tables__-" + tableId); if (tableContent == null) { return topLevelContent; } diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/RegionAttributesNames.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/RegionAttributesNames.java index d5d89b6..341a126 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/RegionAttributesNames.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/RegionAttributesNames.java @@ -43,6 +43,8 @@ public class RegionAttributesNames { public static final String POOL_NAME = "pool-name"; public static final String COMPRESSOR = "compressor"; public static final String OFF_HEAP = "off-heap"; + public static final String ASYNC_EVENT_QUEUE_ID = "async-event-queue-id"; + public static final String GATEWAY_SENDER_ID = "gateway-sender-id"; // Partition attributes public static final String LOCAL_MAX_MEMORY = "local-max-memory"; diff --git a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt index e7cd276..971db79 100644 --- a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt +++ b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt @@ -500,8 +500,8 @@ org/apache/geode/management/internal/cli/domain/MemberConfigurationInfo,false,ca org/apache/geode/management/internal/cli/domain/MemberInformation,true,1,cacheServerList:java/util/List,cacheXmlFilePath:java/lang/String,clientCount:int,cpuUsage:double,groups:java/lang/String,heapUsage:java/lang/String,host:java/lang/String,hostedRegions:java/util/Set,id:java/lang/String,initHeapSize:java/lang/String,isServer:boolean,locatorBindAddress:java/lang/String,locatorPort:int,locators:java/lang/String,logFilePath:java/lang/String,maxHeapSize:java/lang/String,name:java/lang/Str [...] org/apache/geode/management/internal/cli/domain/MemberResult,true,1,errorMessage:java/lang/String,exceptionMessage:java/lang/String,isSuccessful:boolean,memberNameOrId:java/lang/String,opPossible:boolean,successMessage:java/lang/String org/apache/geode/management/internal/cli/domain/PartitionAttributesInfo,true,1,colocatedWith:java/lang/String,fpaInfoList:java/util/List,localMaxMemory:int,nonDefaultAttributes:java/util/Map,partitionResolverName:java/lang/String,recoveryDelay:long,redundantCopies:int,startupRecoveryDelay:long,totalNumBuckets:int -org/apache/geode/management/internal/cli/domain/RegionAttributesInfo,true,1,cacheListenerClassNames:java/util/List,cacheLoaderClassName:java/lang/String,cacheWriterClassName:java/lang/String,cloningEnabled:boolean,compressorClassName:java/lang/String,concurrencyChecksEnabled:boolean,concurrencyLevel:int,dataPolicy:org/apache/geode/cache/DataPolicy,diskStoreName:java/lang/String,enableAsyncConflation:boolean,enableSubscriptionConflation:boolean,entryIdleTimeout:int,entryIdleTimeoutAction: [...] -org/apache/geode/management/internal/cli/domain/RegionDescription,true,1,cndEvictionAttributes:java/util/Map,cndPartitionAttributes:java/util/Map,cndRegionAttributes:java/util/Map,dataPolicy:org/apache/geode/cache/DataPolicy,haslocalDataStorage:boolean,isAccessor:boolean,isLocal:boolean,isPartition:boolean,isPersistent:boolean,isReplicate:boolean,isReplicatedProxy:boolean,name:java/lang/String,regionDescPerMemberMap:java/util/Map,scope:org/apache/geode/cache/Scope +org/apache/geode/management/internal/cli/domain/RegionAttributesInfo,true,336184564012988487,asyncEventQueueIDs:java/util/Set,cacheListenerClassNames:java/util/List,cacheLoaderClassName:java/lang/String,cacheWriterClassName:java/lang/String,cloningEnabled:boolean,compressorClassName:java/lang/String,concurrencyChecksEnabled:boolean,concurrencyLevel:int,dataPolicy:org/apache/geode/cache/DataPolicy,diskStoreName:java/lang/String,enableAsyncConflation:boolean,enableSubscriptionConflation:bo [...] +org/apache/geode/management/internal/cli/domain/RegionDescription,true,6461449275798378332,cndEvictionAttributes:java/util/Map,cndPartitionAttributes:java/util/Map,cndRegionAttributes:java/util/Map,dataPolicy:org/apache/geode/cache/DataPolicy,isAccessor:boolean,isLocal:boolean,isPartition:boolean,isPersistent:boolean,isReplicate:boolean,name:java/lang/String,regionDescPerMemberMap:java/util/Map,scope:org/apache/geode/cache/Scope org/apache/geode/management/internal/cli/domain/RegionDescriptionPerMember,true,1,hostingMember:java/lang/String,isAccessor:boolean,name:java/lang/String,regionAttributesInfo:org/apache/geode/management/internal/cli/domain/RegionAttributesInfo,size:int org/apache/geode/management/internal/cli/domain/RegionInformation,true,1,dataPolicy:org/apache/geode/cache/DataPolicy,isRoot:boolean,name:java/lang/String,parentRegion:java/lang/String,path:java/lang/String,scope:org/apache/geode/cache/Scope,subRegionInformationSet:java/util/Set org/apache/geode/management/internal/cli/domain/StackTracesPerMember,true,1,memberNameOrId:java/lang/String,stackTraces:byte[] diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionDUnitTest.java index 8e22339..e4ddd3a 100644 --- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionDUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionDUnitTest.java @@ -14,23 +14,10 @@ */ package org.apache.geode.management.internal.cli.commands; -import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_TIME_STATISTICS; -import static org.apache.geode.distributed.ConfigurationProperties.GROUPS; -import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS; -import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL; -import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT; -import static org.apache.geode.distributed.ConfigurationProperties.NAME; -import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_SAMPLING_ENABLED; import static org.apache.geode.management.internal.cli.i18n.CliStrings.DESCRIBE_REGION; import static org.apache.geode.management.internal.cli.i18n.CliStrings.DESCRIBE_REGION__NAME; -import static org.apache.geode.management.internal.cli.i18n.CliStrings.GROUP; -import static org.apache.geode.management.internal.cli.i18n.CliStrings.LIST_REGION; -import static org.apache.geode.management.internal.cli.i18n.CliStrings.MEMBER; import static org.assertj.core.api.Assertions.assertThat; -import java.io.Serializable; -import java.util.Properties; - import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; @@ -55,11 +42,10 @@ import org.apache.geode.test.dunit.VM; import org.apache.geode.test.dunit.rules.LocatorServerStartupRule; import org.apache.geode.test.dunit.rules.MemberVM; import org.apache.geode.test.junit.categories.DistributedTest; -import org.apache.geode.test.junit.categories.FlakyTest; import org.apache.geode.test.junit.rules.GfshCommandRule; @Category(DistributedTest.class) -public class DescribeRegionDUnitTest implements Serializable { +public class DescribeRegionDUnitTest { private static final String REGION1 = "region1"; private static final String REGION2 = "region2"; private static final String REGION3 = "region3"; @@ -67,14 +53,8 @@ public class DescribeRegionDUnitTest implements Serializable { private static final String SUBREGION1B = "subregion1B"; private static final String SUBREGION1C = "subregion1C"; private static final String PR1 = "PR1"; - private static final String LOCALREGIONONMANAGER = "LocalRegionOnManager"; - - private static final String LOCATOR_NAME = "Locator"; - private static final String SERVER1_NAME = "Server-1"; - private static final String SERVER2_NAME = "Server-2"; - private static final String GROUP1_NAME = "G1"; - private static final String GROUP2_NAME = "G2"; - private static final String GROUP3_NAME = "G3"; + private static final String LOCAL_REGION = "LocalRegion"; + private static final String PART1_NAME = "Par1"; private static final String PART2_NAME = "Par2"; @@ -82,22 +62,16 @@ public class DescribeRegionDUnitTest implements Serializable { public static LocatorServerStartupRule lsRule = new LocatorServerStartupRule(); @ClassRule - public static GfshCommandRule gfshCommandRule = new GfshCommandRule(); + public static GfshCommandRule gfsh = new GfshCommandRule(); @BeforeClass public static void setupSystem() throws Exception { - final Properties locatorProps = createProperties(LOCATOR_NAME, GROUP3_NAME); - MemberVM locator = lsRule.startLocatorVM(0, locatorProps); - - final Properties managerProps = createProperties(SERVER1_NAME, GROUP1_NAME); - managerProps.setProperty(LOCATORS, "localhost[" + locator.getPort() + "]"); - MemberVM manager = lsRule.startServerVM(1, managerProps, locator.getPort()); - - final Properties serverProps = createProperties(SERVER2_NAME, GROUP2_NAME); - MemberVM server = lsRule.startServerVM(2, serverProps, locator.getPort()); + MemberVM locator = lsRule.startLocatorVM(0); + MemberVM server1 = lsRule.startServerVM(1, "group1", locator.getPort()); + MemberVM server2 = lsRule.startServerVM(2, "group2", locator.getPort()); - manager.invoke(() -> { - final Cache cache = CacheFactory.getAnyInstance(); + server1.invoke(() -> { + final Cache cache = LocatorServerStartupRule.getCache(); RegionFactory<String, Integer> dataRegionFactory = cache.createRegionFactory(RegionShortcut.PARTITION); dataRegionFactory.setConcurrencyLevel(4); @@ -114,11 +88,11 @@ public class DescribeRegionDUnitTest implements Serializable { dataRegionFactory.setPartitionAttributes(pa); dataRegionFactory.create(PR1); - createLocalRegion(LOCALREGIONONMANAGER); + createLocalRegion(LOCAL_REGION); }); - server.invoke(() -> { - final Cache cache = CacheFactory.getAnyInstance(); + server2.invoke(() -> { + final Cache cache = LocatorServerStartupRule.getCache(); RegionFactory<String, Integer> dataRegionFactory = cache.createRegionFactory(RegionShortcut.PARTITION); dataRegionFactory.setConcurrencyLevel(4); @@ -137,23 +111,31 @@ public class DescribeRegionDUnitTest implements Serializable { createRegionsWithSubRegions(); }); - gfshCommandRule.connectAndVerify(locator); + gfsh.connectAndVerify(locator); + gfsh.executeAndAssertThat("create async-event-queue --id=queue1 --group=group1 " + + "--listener=org.apache.geode.internal.cache.wan.MyAsyncEventListener").statusIsSuccess(); + + locator.waitTillAsyncEventQueuesAreReadyOnServers("queue1", 1); + gfsh.executeAndAssertThat( + "create region --name=region4 --type=REPLICATE --async-event-queue-id=queue1") + .statusIsSuccess(); + } @Test - public void describeRegionsOnServer2() throws Exception { + public void describeRegionOnBothServers() throws Exception { CommandStringBuilder csb = new CommandStringBuilder(DESCRIBE_REGION); csb.addOption(DESCRIBE_REGION__NAME, PR1); - gfshCommandRule.executeAndAssertThat(csb.toString()).statusIsSuccess().containsOutput(PR1, - "Server"); + gfsh.executeAndAssertThat(csb.toString()).statusIsSuccess().containsOutput(PR1, "server-1", + "server-2"); } @Test - public void describeRegionsOnServer1() throws Exception { + public void describeLocalRegionOnlyOneServer1() throws Exception { CommandStringBuilder csb = new CommandStringBuilder(DESCRIBE_REGION); - csb.addOption(DESCRIBE_REGION__NAME, LOCALREGIONONMANAGER); - gfshCommandRule.executeAndAssertThat(csb.toString()).statusIsSuccess() - .containsOutput(LOCALREGIONONMANAGER, SERVER1_NAME); + csb.addOption(DESCRIBE_REGION__NAME, LOCAL_REGION); + gfsh.executeAndAssertThat(csb.toString()).statusIsSuccess() + .containsOutput(LOCAL_REGION, "server-1").doesNotContainOutput("server-2"); } /** @@ -172,7 +154,7 @@ public class DescribeRegionDUnitTest implements Serializable { CommandStringBuilder csb = new CommandStringBuilder(DESCRIBE_REGION); csb.addOption(DESCRIBE_REGION__NAME, regionName); String commandString = csb.toString(); - gfshCommandRule.executeAndAssertThat(commandString).statusIsSuccess().containsOutput(regionName, + gfsh.executeAndAssertThat(commandString).statusIsSuccess().containsOutput(regionName, RegionAttributesNames.COMPRESSOR, RegionEntryContext.DEFAULT_COMPRESSION_PROVIDER); // Destroy compressed region @@ -183,15 +165,10 @@ public class DescribeRegionDUnitTest implements Serializable { }); } - private static Properties createProperties(String name, String groups) { - Properties props = new Properties(); - props.setProperty(MCAST_PORT, "0"); - props.setProperty(LOG_LEVEL, "info"); - props.setProperty(STATISTIC_SAMPLING_ENABLED, "true"); - props.setProperty(ENABLE_TIME_STATISTICS, "true"); - props.setProperty(NAME, name); - props.setProperty(GROUPS, groups); - return props; + @Test + public void describeRegionWithAsyncEventQueue() throws Exception { + gfsh.executeAndAssertThat("describe region --name=region4").statusIsSuccess() + .containsOutput("async-event-queue-id", "queue1"); } private static void createLocalRegion(final String regionName) { diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionIntegrationTest.java index e0f990f..e455fff7 100644 --- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionIntegrationTest.java +++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionIntegrationTest.java @@ -15,6 +15,7 @@ package org.apache.geode.management.internal.cli.commands; +import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; @@ -35,35 +36,28 @@ public class DescribeRegionIntegrationTest { @ClassRule public static ServerStarterRule server = new ServerStarterRule() .withRegion(RegionShortcut.REPLICATE, REGION_NAME).withName(MEMBER_NAME) - .withProperty("groups", GROUP_NAME).withJMXManager().withEmbeddedLocator().withAutoStart(); + .withProperty("groups", GROUP_NAME).withJMXManager().withAutoStart(); @Rule - public GfshCommandRule gfsh = new GfshCommandRule(); + public GfshCommandRule gfsh = + new GfshCommandRule(server::getJmxPort, PortType.jmxManager).withTimeout(2); @Test public void commandFailsWhenNotConnected() throws Exception { + gfsh.disconnect(); gfsh.executeAndAssertThat("describe region").statusIsError() .containsOutput("was found but is not currently available"); } @Test - public void commandFailsWithoutNameOption() throws Exception { - String cmd = "describe region"; - gfsh.connectAndVerify(server.getEmbeddedLocatorPort(), PortType.locator); - gfsh.executeAndAssertThat(cmd).statusIsError().containsOutput("You should specify option"); - } - - @Test public void commandFailsWithBadNameOption() throws Exception { String cmd = "describe region --name=invalid-region-name"; - gfsh.connectAndVerify(server.getEmbeddedLocatorPort(), PortType.locator); gfsh.executeAndAssertThat(cmd).statusIsError().containsOutput("invalid-region-name not found"); } @Test public void commandSucceedsWithGoodNameOption() throws Exception { String cmd = "describe region --name=" + REGION_NAME; - gfsh.connectAndVerify(server.getEmbeddedLocatorPort(), PortType.locator); gfsh.executeAndAssertThat(cmd).statusIsSuccess().containsOutput("Name", "Data Policy", "Hosting Members"); } diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionJUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionJUnitTest.java new file mode 100644 index 0000000..0faca89 --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionJUnitTest.java @@ -0,0 +1,188 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 + * + * http://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.apache.geode.management.internal.cli.commands; + +import static org.apache.geode.cache.DataPolicy.NORMAL; +import static org.apache.geode.cache.Scope.DISTRIBUTED_ACK; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import org.apache.geode.management.internal.cli.GfshParseResult; +import org.apache.geode.management.internal.cli.domain.RegionDescriptionPerMember; +import org.apache.geode.management.internal.cli.json.GfJsonObject; +import org.apache.geode.management.internal.cli.result.CommandResult; +import org.apache.geode.test.junit.assertions.CommandResultAssert; +import org.apache.geode.test.junit.categories.UnitTest; +import org.apache.geode.test.junit.rules.GfshParserRule; + +@Category(UnitTest.class) +public class DescribeRegionJUnitTest { + + @ClassRule + public static GfshParserRule gfsh = new GfshParserRule(); + + private DescribeRegionCommand command; + private static String COMMAND = "describe region"; + private List<RegionDescriptionPerMember> functionResults; + private static final String regionName = "testRegion"; + + @Before + public void setup() { + command = spy(DescribeRegionCommand.class); + functionResults = new ArrayList<>(); + doReturn(functionResults).when(command).getFunctionResultFromMembers(any()); + } + + private RegionDescriptionPerMember createRegionDescriptionPerMember(String memberName, + Map<String, String> evictionMap, Map<String, String> partitionMap, + Map<String, String> regionMap) { + RegionDescriptionPerMember descriptionPerMember = mock(RegionDescriptionPerMember.class); + when(descriptionPerMember.getNonDefaultEvictionAttributes()).thenReturn(evictionMap); + when(descriptionPerMember.getNonDefaultPartitionAttributes()).thenReturn(partitionMap); + when(descriptionPerMember.getNonDefaultRegionAttributes()).thenReturn(regionMap); + when(descriptionPerMember.getHostingMember()).thenReturn(memberName); + when(descriptionPerMember.getScope()).thenReturn(DISTRIBUTED_ACK); + when(descriptionPerMember.getDataPolicy()).thenReturn(NORMAL); + when(descriptionPerMember.getName()).thenReturn(regionName); + + return descriptionPerMember; + } + + @Test + public void nameIsMandatory() throws Exception { + gfsh.executeAndAssertThat(command, COMMAND).statusIsError().containsOutput("Invalid command"); + } + + @Test + public void regionPathConverted() throws Exception { + GfshParseResult parseResult = gfsh.parse(COMMAND + " --name=test"); + assertThat(parseResult.getParamValueAsString("name")).isEqualTo("/test"); + } + + @Test + public void gettingDescriptionFromOneMember() throws Exception { + Map<String, String> evictionAttr = new HashMap<>(); + Map<String, String> partitionAttr = new HashMap<>(); + Map<String, String> regionAttr = new HashMap<>(); + + evictionAttr.put("evictKey", "evictVal"); + partitionAttr.put("partKey", "partVal"); + regionAttr.put("regKey", "regVal"); + + RegionDescriptionPerMember descriptionPerMember = + createRegionDescriptionPerMember("mockA", evictionAttr, partitionAttr, regionAttr); + functionResults.add(descriptionPerMember); + + CommandResultAssert commandAssert = + gfsh.executeAndAssertThat(command, COMMAND + " --name=" + regionName).statusIsSuccess() + .doesNotContainOutput("Non-Default Attributes Specific To"); + + GfJsonObject shared = getSharedAttributedJson(commandAssert.getCommandResult()); + GfJsonObject unique = getMemberSpecificAttributeJson(commandAssert.getCommandResult()); + + assertThat(shared.toString()).contains("regKey", "regVal", "evictKey", "evictVal", "partKey", + "partVal"); + assertThat(unique.toString()).isEqualTo("{}"); + } + + @Test + public void gettingDescriptionFromTwoIdenticalMembers() throws Exception { + Map<String, String> evictionAttr = new HashMap<>(); + Map<String, String> partitionAttr = new HashMap<>(); + Map<String, String> regionAttr = new HashMap<>(); + + evictionAttr.put("evictKey", "evictVal"); + partitionAttr.put("partKey", "partVal"); + regionAttr.put("regKey", "regVal"); + + RegionDescriptionPerMember descriptionPerMemberA = + createRegionDescriptionPerMember("mockA", evictionAttr, partitionAttr, regionAttr); + RegionDescriptionPerMember descriptionPerMemberB = + createRegionDescriptionPerMember("mockB", evictionAttr, partitionAttr, regionAttr); + functionResults.add(descriptionPerMemberA); + functionResults.add(descriptionPerMemberB); + + CommandResultAssert commandAssert = + gfsh.executeAndAssertThat(command, COMMAND + " --name=" + regionName).statusIsSuccess() + .doesNotContainOutput("Non-Default Attributes Specific To"); + + GfJsonObject shared = getSharedAttributedJson(commandAssert.getCommandResult()); + GfJsonObject unique = getMemberSpecificAttributeJson(commandAssert.getCommandResult()); + + assertThat(shared.toString()).contains("regKey", "regVal", "evictKey", "evictVal", "partKey", + "partVal"); + assertThat(unique.toString()).isEqualTo("{}"); + } + + @Test + public void gettingDescriptionFromTwoDifferentMembers() throws Exception { + Map<String, String> evictionAttrA = new HashMap<>(); + Map<String, String> partitionAttrA = new HashMap<>(); + Map<String, String> regionAttrA = new HashMap<>(); + + evictionAttrA.put("sharedEvictionKey", "sharedEvictionValue"); + partitionAttrA.put("sharedPartitionKey", "uniquePartitionValue_A"); + regionAttrA.put("uniqueRegionKey_A", "uniqueRegionValue_A"); + + Map<String, String> evictionAttrB = new HashMap<>(); + Map<String, String> partitionAttrB = new HashMap<>(); + Map<String, String> regionAttrB = new HashMap<>(); + + evictionAttrB.put("sharedEvictionKey", "sharedEvictionValue"); + partitionAttrB.put("sharedPartitionKey", "uniquePartitionValue_B"); + regionAttrB.put("uniqueRegionKey_B", "uniqueRegionValue_B"); + + RegionDescriptionPerMember descriptionPerMemberA = + createRegionDescriptionPerMember("mockA", evictionAttrA, partitionAttrA, regionAttrA); + RegionDescriptionPerMember descriptionPerMemberB = + createRegionDescriptionPerMember("mockB", evictionAttrB, partitionAttrB, regionAttrB); + functionResults.add(descriptionPerMemberA); + functionResults.add(descriptionPerMemberB); + + CommandResultAssert commandAssert = + gfsh.executeAndAssertThat(command, COMMAND + " --name=" + regionName).statusIsSuccess(); + + GfJsonObject shared = getSharedAttributedJson(commandAssert.getCommandResult()); + GfJsonObject unique = getMemberSpecificAttributeJson(commandAssert.getCommandResult()); + + assertThat(shared.toString()).contains("Eviction", "sharedEvictionKey", "sharedEvictionValue"); + assertThat(unique.toString()).contains("sharedPartitionKey", "uniquePartitionValue_A", + "uniqueRegionKey_A", "uniqueRegionValue_A", "sharedPartitionKey", "uniquePartitionValue_B", + "uniqueRegionKey_B", "uniqueRegionValue_B"); + } + + private GfJsonObject getSharedAttributedJson(CommandResult commandResult) { + return commandResult.getTableContent(0, 0, 0); + } + + private GfJsonObject getMemberSpecificAttributeJson(CommandResult commandResult) { + return commandResult.getTableContent(0, 1, 0); + } +} diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/domain/RegionDescriptionJUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/domain/RegionDescriptionJUnitTest.java new file mode 100644 index 0000000..94f7f6a --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/domain/RegionDescriptionJUnitTest.java @@ -0,0 +1,255 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 + * + * http://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.apache.geode.management.internal.cli.domain; + +import static org.apache.geode.cache.DataPolicy.NORMAL; +import static org.apache.geode.cache.Scope.DISTRIBUTED_ACK; +import static org.apache.geode.cache.Scope.LOCAL; +import static org.apache.geode.management.internal.cli.domain.RegionDescription.findCommon; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import org.apache.geode.test.junit.categories.UnitTest; + +@Category(UnitTest.class) +public class RegionDescriptionJUnitTest { + private static final String evictionKeyShared = "sharedEvictionKey"; + private static final String partKeyShared = "sharedPartitionKey"; + private static final String regKeyShared = "sharedRegionKey"; + private static final String evictionValueShared = "sharedEvictionValue"; + private static final String partValueShared = "sharedPartitionValue"; + private static final String regValueShared = "sharedRegionValue"; + + private static final String evictionKeyA = "uniqueEvictionKey_A"; + private static final String partKeyA = "uniquePartitionKey_A"; + private static final String regKeyA = "uniqueRegionKey_A"; + private static final String evictionValueA = "uniqueEvictionValue_A"; + private static final String partValueA = "uniquePartitionValue_A"; + private static final String regValueA = "uniqueRegionValue_A"; + + private static final String evictionKeyB = "uniqueEvictionKey_B"; + private static final String partKeyB = "uniquePartitionKey_B"; + private static final String regKeyB = "uniqueRegionKey_B"; + private static final String evictionValueB = "uniqueEvictionValue_B"; + private static final String partValueB = "uniquePartitionValue_B"; + private static final String regValueB = "uniqueRegionValue_B"; + + public static final String regionName = "mockRegion1"; + + @Test + public void findCommonRemovesUnsharedKeys() { + Map<String, String> commonMap = new HashMap<>(); + commonMap.put(evictionKeyShared, evictionValueShared); + commonMap.put(partKeyShared, partValueShared); + commonMap.put(regKeyShared, regValueShared); + commonMap.put(evictionKeyA, evictionValueA); + commonMap.put(partKeyA, partValueA); + + Map<String, String> comparisonMap = new HashMap<>(); + comparisonMap.put(evictionKeyShared, evictionValueShared); + comparisonMap.put(partKeyShared, partValueShared); + comparisonMap.put(regKeyShared, regValueShared); + comparisonMap.put(evictionKeyB, evictionValueB); + comparisonMap.put(regKeyB, regValueB); + + findCommon(commonMap, comparisonMap); + + assertThat(commonMap).containsOnlyKeys(evictionKeyShared, partKeyShared, regKeyShared); + } + + @Test + public void findCommonRemovesKeysWithDisagreeingValues() { + Map<String, String> commonMap = new HashMap<>(); + commonMap.put(evictionKeyShared, evictionValueShared); + commonMap.put(partKeyShared, partValueA); + commonMap.put(regKeyShared, regValueA); + + Map<String, String> comparisonMap = new HashMap<>(); + comparisonMap.put(evictionKeyShared, evictionValueShared); + comparisonMap.put(partKeyShared, partValueB); + comparisonMap.put(regKeyShared, regValueB); + + findCommon(commonMap, comparisonMap); + + assertThat(commonMap).containsOnlyKeys(evictionKeyShared); + } + + @Test + public void findCommonRemovesDisagreeingKeysInvolvingNull() { + Map<String, String> commonMap = new HashMap<>(); + commonMap.put(evictionKeyShared, evictionValueShared); + commonMap.put(partKeyShared, partValueA); + commonMap.put(regKeyShared, null); + + Map<String, String> comparisonMap = new HashMap<>(); + comparisonMap.put(evictionKeyShared, evictionValueShared); + comparisonMap.put(partKeyShared, null); + comparisonMap.put(regKeyShared, regValueB); + + findCommon(commonMap, comparisonMap); + + assertThat(commonMap).containsOnlyKeys(evictionKeyShared); + } + + + @Test + public void singleAddDefinesDescription() { + RegionDescriptionPerMember mockA = getMockRegionDescriptionPerMember_A(); + RegionDescription description = new RegionDescription(); + description.add(mockA); + + assertThat(description.getCndEvictionAttributes()) + .isEqualTo(mockA.getNonDefaultEvictionAttributes()); + assertThat(description.getCndPartitionAttributes()) + .isEqualTo(mockA.getNonDefaultPartitionAttributes()); + assertThat(description.getCndRegionAttributes()) + .isEqualTo(mockA.getNonDefaultRegionAttributes()); + } + + @Test + public void multipleAddsMergeAsExpected() { + RegionDescriptionPerMember mockA = getMockRegionDescriptionPerMember_A(); + RegionDescriptionPerMember mockB = getMockRegionDescriptionPerMember_B(); + RegionDescription description = new RegionDescription(); + description.add(mockA); + description.add(mockB); + + Map<String, String> sharedEviction = new HashMap<>(); + sharedEviction.put(evictionKeyShared, evictionValueShared); + Map<String, String> sharedRegion = new HashMap<>(); + sharedRegion.put(regKeyShared, regValueShared); + Map<String, String> sharedPartition = new HashMap<>(); + sharedPartition.put(partKeyShared, partValueShared); + + assertThat(description.getCndEvictionAttributes()).isEqualTo(sharedEviction); + assertThat(description.getCndPartitionAttributes()).isEqualTo(sharedPartition); + assertThat(description.getCndRegionAttributes()).isEqualTo(sharedRegion); + + assertThat(description.getRegionDescriptionPerMemberMap()) + .containsOnlyKeys(mockA.getHostingMember(), mockB.getHostingMember()) + .containsEntry(mockA.getHostingMember(), mockA) + .containsEntry(mockB.getHostingMember(), mockB); + } + + @Test + public void outOfScopeAddGetsIgnored() { + RegionDescriptionPerMember mockA = getMockRegionDescriptionPerMember_A(); + RegionDescriptionPerMember mockB = getMockRegionDescriptionPerMember_OutOfScope(); + RegionDescription description = new RegionDescription(); + description.add(mockA); + description.add(mockB); + + assertThat(description.getCndEvictionAttributes()) + .isEqualTo(mockA.getNonDefaultEvictionAttributes()); + assertThat(description.getCndPartitionAttributes()) + .isEqualTo(mockA.getNonDefaultPartitionAttributes()); + assertThat(description.getCndRegionAttributes()) + .isEqualTo(mockA.getNonDefaultRegionAttributes()); + } + + private RegionDescriptionPerMember getMockRegionDescriptionPerMember_A() { + Map<String, String> mockNonDefaultEvictionAttributes = new HashMap<>(); + mockNonDefaultEvictionAttributes.put(evictionKeyShared, evictionValueShared); + mockNonDefaultEvictionAttributes.put(evictionKeyA, evictionValueA); + + Map<String, String> mockNonDefaultPartitionAttributes = new HashMap<>(); + mockNonDefaultPartitionAttributes.put(partKeyShared, partValueShared); + mockNonDefaultPartitionAttributes.put(partKeyA, partValueA); + + Map<String, String> mockNonDefaultRegionAttributes = new HashMap<>(); + mockNonDefaultRegionAttributes.put(regKeyShared, regValueShared); + mockNonDefaultRegionAttributes.put(regKeyA, regValueA); + + RegionDescriptionPerMember mockDescPerMember = mock(RegionDescriptionPerMember.class); + + when(mockDescPerMember.getNonDefaultEvictionAttributes()) + .thenReturn(mockNonDefaultEvictionAttributes); + when(mockDescPerMember.getNonDefaultPartitionAttributes()) + .thenReturn(mockNonDefaultPartitionAttributes); + when(mockDescPerMember.getNonDefaultRegionAttributes()) + .thenReturn(mockNonDefaultRegionAttributes); + when(mockDescPerMember.getHostingMember()).thenReturn("mockMemberA"); + when(mockDescPerMember.getScope()).thenReturn(DISTRIBUTED_ACK); + when(mockDescPerMember.getDataPolicy()).thenReturn(NORMAL); + when(mockDescPerMember.getName()).thenReturn(regionName); + + return mockDescPerMember; + } + + private RegionDescriptionPerMember getMockRegionDescriptionPerMember_B() { + Map<String, String> mockNonDefaultEvictionAttributes = new HashMap<>(); + mockNonDefaultEvictionAttributes.put(evictionKeyShared, evictionValueShared); + mockNonDefaultEvictionAttributes.put(evictionKeyB, evictionValueB); + + Map<String, String> mockNonDefaultPartitionAttributes = new HashMap<>(); + mockNonDefaultPartitionAttributes.put(partKeyShared, partValueShared); + mockNonDefaultPartitionAttributes.put(partKeyB, partValueB); + + Map<String, String> mockNonDefaultRegionAttributes = new HashMap<>(); + mockNonDefaultRegionAttributes.put(regKeyShared, regValueShared); + mockNonDefaultRegionAttributes.put(regKeyB, regValueB); + + RegionDescriptionPerMember mockDescPerMember = mock(RegionDescriptionPerMember.class); + + when(mockDescPerMember.getNonDefaultEvictionAttributes()) + .thenReturn(mockNonDefaultEvictionAttributes); + when(mockDescPerMember.getNonDefaultPartitionAttributes()) + .thenReturn(mockNonDefaultPartitionAttributes); + when(mockDescPerMember.getNonDefaultRegionAttributes()) + .thenReturn(mockNonDefaultRegionAttributes); + when(mockDescPerMember.getHostingMember()).thenReturn("mockMemberB"); + when(mockDescPerMember.getScope()).thenReturn(DISTRIBUTED_ACK); + when(mockDescPerMember.getDataPolicy()).thenReturn(NORMAL); + when(mockDescPerMember.getName()).thenReturn(regionName); + + return mockDescPerMember; + } + + private RegionDescriptionPerMember getMockRegionDescriptionPerMember_OutOfScope() { + Map<String, String> mockNonDefaultEvictionAttributes = new HashMap<>(); + mockNonDefaultEvictionAttributes.put(evictionKeyShared, evictionValueShared); + + Map<String, String> mockNonDefaultPartitionAttributes = new HashMap<>(); + mockNonDefaultPartitionAttributes.put(partKeyShared, partValueShared); + + Map<String, String> mockNonDefaultRegionAttributes = new HashMap<>(); + mockNonDefaultRegionAttributes.put(regKeyShared, regValueShared); + + RegionDescriptionPerMember mockDescPerMember = mock(RegionDescriptionPerMember.class); + + when(mockDescPerMember.getNonDefaultEvictionAttributes()) + .thenReturn(mockNonDefaultEvictionAttributes); + when(mockDescPerMember.getNonDefaultPartitionAttributes()) + .thenReturn(mockNonDefaultPartitionAttributes); + when(mockDescPerMember.getNonDefaultRegionAttributes()) + .thenReturn(mockNonDefaultRegionAttributes); + when(mockDescPerMember.getHostingMember()).thenReturn("mockMemberC"); + when(mockDescPerMember.getScope()).thenReturn(LOCAL); + when(mockDescPerMember.getDataPolicy()).thenReturn(NORMAL); + when(mockDescPerMember.getName()).thenReturn(regionName); + + return mockDescPerMember; + } + + +} diff --git a/geode-core/src/test/java/org/apache/geode/test/dunit/rules/MemberVM.java b/geode-core/src/test/java/org/apache/geode/test/dunit/rules/MemberVM.java index 2f0d729..71b3396 100644 --- a/geode-core/src/test/java/org/apache/geode/test/dunit/rules/MemberVM.java +++ b/geode-core/src/test/java/org/apache/geode/test/dunit/rules/MemberVM.java @@ -15,15 +15,11 @@ package org.apache.geode.test.dunit.rules; -import static org.awaitility.Awaitility.await; - import java.io.File; import java.util.Arrays; -import java.util.concurrent.TimeUnit; import org.apache.commons.io.FileUtils; -import org.apache.geode.management.DistributedSystemMXBean; import org.apache.geode.test.dunit.AsyncInvocation; import org.apache.geode.test.dunit.SerializableCallableIF; import org.apache.geode.test.dunit.SerializableRunnableIF; diff --git a/geode-core/src/test/java/org/apache/geode/test/junit/assertions/CommandResultAssert.java b/geode-core/src/test/java/org/apache/geode/test/junit/assertions/CommandResultAssert.java index 382b65c..40d1469 100644 --- a/geode-core/src/test/java/org/apache/geode/test/junit/assertions/CommandResultAssert.java +++ b/geode-core/src/test/java/org/apache/geode/test/junit/assertions/CommandResultAssert.java @@ -42,6 +42,10 @@ public class CommandResultAssert super(new CommandResultExecution(output, commandResult), CommandResultAssert.class); } + public CommandResult getCommandResult() { + return actual.getCommandResult(); + } + /** * Verifies that the gfsh output contains the given key, value pair. * diff --git a/geode-wan/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionDUnitTest.java b/geode-wan/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionDUnitTest.java new file mode 100644 index 0000000..24d686e --- /dev/null +++ b/geode-wan/src/test/java/org/apache/geode/management/internal/cli/commands/DescribeRegionDUnitTest.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 + * + * http://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.apache.geode.management.internal.cli.commands; + +import static org.apache.geode.distributed.ConfigurationProperties.DISTRIBUTED_SYSTEM_ID; +import static org.apache.geode.distributed.ConfigurationProperties.REMOTE_LOCATORS; + +import java.util.Properties; + +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import org.apache.geode.test.dunit.rules.LocatorServerStartupRule; +import org.apache.geode.test.dunit.rules.MemberVM; +import org.apache.geode.test.junit.categories.DistributedTest; +import org.apache.geode.test.junit.rules.GfshCommandRule; + +@Category(DistributedTest.class) +public class DescribeRegionDUnitTest { + + @ClassRule + public static LocatorServerStartupRule lsRule = new LocatorServerStartupRule(); + + @ClassRule + public static GfshCommandRule gfsh = new GfshCommandRule(); + + @Test + public void describeRegionWithGatewayAndAsyncEventQueue() throws Exception { + Properties props = new Properties(); + props.setProperty(DISTRIBUTED_SYSTEM_ID, "" + 1); + MemberVM sending_locator = lsRule.startLocatorVM(1, props); + + props.setProperty(DISTRIBUTED_SYSTEM_ID, "" + 2); + props.setProperty(REMOTE_LOCATORS, "localhost[" + sending_locator.getPort() + "]"); + lsRule.startLocatorVM(2, props); + + lsRule.startServerVM(3, "group1", sending_locator.getPort()); + lsRule.startServerVM(4, "group2", sending_locator.getPort()); + + gfsh.connectAndVerify(sending_locator); + gfsh.executeAndAssertThat("create async-event-queue --id=queue1 --group=group1 " + + "--listener=org.apache.geode.internal.cache.wan.MyAsyncEventListener").statusIsSuccess(); + gfsh.executeAndAssertThat("create gateway-sender --id=sender1 --remote-distributed-system-id=2") + .statusIsSuccess(); + sending_locator.waitTillAsyncEventQueuesAreReadyOnServers("queue1", 1); + sending_locator.waitTilGatewaySendersAreReady(2); + + gfsh.executeAndAssertThat( + "create region --name=region4 --type=REPLICATE --async-event-queue-id=queue1 --gateway-sender-id=sender1") + .statusIsSuccess(); + + gfsh.executeAndAssertThat("describe region --name=region4").statusIsSuccess() + .containsOutput("gateway-sender-id", "sender1", "async-event-queue-id", "queue1"); + } +} -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
