This closes #205

GEODE-11: Adding stats option to list lucene index gfsh command

Added an option to display lucene index stats in the list lucene index command. 
Added junit and dunit tests to verify the same.

GEODE-11: Added describe lucene index gfsh command

Added describe lucene index gfsh command that takes the index name and region 
as arguments and displays information about the lucene index (fields, analyzers 
and stats). Also added junit and dunit tests for the same.

Signed-off-by: Gester Zhou <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/ce0b7e7d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/ce0b7e7d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/ce0b7e7d

Branch: refs/heads/master
Commit: ce0b7e7df89616c5f4a4d9d41ed0d63a24978dd0
Parents: 8a28f52
Author: Aparna Dharmakkan <[email protected]>
Authored: Tue Jul 12 16:31:02 2016 -0700
Committer: zhouxh <[email protected]>
Committed: Thu Jul 14 11:14:28 2016 -0700

----------------------------------------------------------------------
 .../lucene/internal/cli/LuceneCliStrings.java   |  24 +++-
 .../internal/cli/LuceneIndexCommands.java       |  80 ++++++++++--
 .../lucene/internal/cli/LuceneIndexDetails.java |  30 ++++-
 .../lucene/internal/cli/LuceneIndexInfo.java    |   4 +
 .../functions/LuceneDescribeIndexFunction.java  |  68 ++++++++++
 .../cli/LuceneIndexCommandsDUnitTest.java       |  72 +++++++++--
 .../cli/LuceneIndexCommandsJUnitTest.java       | 124 +++++++++++++++++--
 .../LuceneDescribeIndexFunctionJUnitTest.java   | 103 +++++++++++++++
 8 files changed, 463 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/ce0b7e7d/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneCliStrings.java
----------------------------------------------------------------------
diff --git 
a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneCliStrings.java
 
b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneCliStrings.java
index 3248e75..282e691 100644
--- 
a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneCliStrings.java
+++ 
b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneCliStrings.java
@@ -19,17 +19,22 @@
 package com.gemstone.gemfire.cache.lucene.internal.cli;
 
 public class LuceneCliStrings {
-  //List Lucene Index commands
+  //Common parameters/options
+  public static final String LUCENE__INDEX_NAME = "name";
+  public static final String LUCENE__REGION_PATH = "region";
+
+  //List lucene index commands
   public static final String LUCENE_LIST_INDEX = "list lucene index";
   public static final String LUCENE_LIST_INDEX__HELP = "Display the list of 
lucene indexes created for all members.";
   public static final String LUCENE_LIST_INDEX__ERROR_MESSAGE = "An error 
occurred while collecting all lucene index information across the Geode 
cluster: %1$s";
-  public static final String LUCENE_LIST_INDEX__INDEXES_NOT_FOUND_MESSAGE = 
"No lucene indexes Found";
+  public static final String LUCENE_LIST_INDEX__INDEXES_NOT_FOUND_MESSAGE = 
"No lucene indexes found";
+  public static final String LUCENE_LIST_INDEX__STATS = "stats";
+  public static final String LUCENE_LIST_INDEX__STATS__HELP = "Display lucene 
index stats";
 
+  //Create lucene index commands 
   public static final String LUCENE_CREATE_INDEX = "create lucene index";
   public static final String LUCENE_CREATE_INDEX__HELP = "Create a lucene 
index that can be used to execute queries.";
-  public static final String LUCENE_CREATE_INDEX__NAME = "name";
   public static final String LUCENE_CREATE_INDEX__NAME__HELP = "Name of the 
lucene index to create.";
-  public static final String LUCENE_CREATE_INDEX__REGION = "region";
   public static final String LUCENE_CREATE_INDEX__REGION_HELP = "Name/Path of 
the region where the lucene index is created on.";
   public static final String LUCENE_CREATE_INDEX__FIELD = "field";
   public static final String LUCENE_CREATE_INDEX__FIELD_HELP = "fields on the 
region values which are stored in the lucene index.";
@@ -37,7 +42,6 @@ public class LuceneCliStrings {
   public static final String LUCENE_CREATE_INDEX__ANALYZER_HELP = "Type of the 
analyzer for each field.";
   public static final String LUCENE_CREATE_INDEX__GROUP = "group";
   public static final String LUCENE_CREATE_INDEX__GROUP__HELP = "Group of 
members in which the lucene index will be created.";
-
   public static final String CREATE_INDEX__SUCCESS__MSG = "Index successfully 
created with following details";
   public static final String CREATE_INDEX__FAILURE__MSG = "Failed to create 
index \"{0}\" due to following reasons";
   public static final String CREATE_INDEX__NAME__MSG = "Name       : {0}";
@@ -45,4 +49,14 @@ public class LuceneCliStrings {
   public static final String CREATE_INDEX__MEMBER__MSG = "Members which 
contain the index";
   public static final String CREATE_INDEX__NUMBER__AND__MEMBER = "{0}. {1}";
   public static final String CREATE_INDEX__EXCEPTION__OCCURRED__ON = "Occurred 
on following members";
+  
+  //Describe lucene index commands
+  public static final String LUCENE_DESCRIBE_INDEX = "describe lucene index";
+  public static final String LUCENE_DESCRIBE_INDEX__HELP = "Display the 
describe of lucene indexes created for all members.";
+  public static final String LUCENE_DESCRIBE_INDEX__ERROR_MESSAGE = "An error 
occurred while collecting lucene index information across the Geode cluster: 
%1$s";
+  public static final String LUCENE_DESCRIBE_INDEX__NAME__HELP = "Name of the 
lucene index to describe.";
+  public static final String LUCENE_DESCRIBE_INDEX__REGION_HELP = "Name/Path 
of the region where the lucene index to be described exists.";
+
+
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/ce0b7e7d/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommands.java
----------------------------------------------------------------------
diff --git 
a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommands.java
 
b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommands.java
index 4715389..30028be 100755
--- 
a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommands.java
+++ 
b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommands.java
@@ -16,6 +16,10 @@
  */
 package com.gemstone.gemfire.cache.lucene.internal.cli;
 
+import static com.gemstone.gemfire.cache.operations.OperationContext.*;
+
+import java.util.ArrayList;
+
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -31,9 +35,11 @@ import org.springframework.shell.core.annotation.CliOption;
 import com.gemstone.gemfire.SystemFailure;
 import com.gemstone.gemfire.cache.Cache;
 import com.gemstone.gemfire.cache.execute.Execution;
+import com.gemstone.gemfire.cache.execute.FunctionAdapter;
 import com.gemstone.gemfire.cache.execute.FunctionInvocationTargetException;
 import com.gemstone.gemfire.cache.execute.ResultCollector;
 import 
com.gemstone.gemfire.cache.lucene.internal.cli.functions.LuceneCreateIndexFunction;
+import 
com.gemstone.gemfire.cache.lucene.internal.cli.functions.LuceneDescribeIndexFunction;
 import 
com.gemstone.gemfire.cache.lucene.internal.cli.functions.LuceneListIndexFunction;
 import com.gemstone.gemfire.distributed.DistributedMember;
 import com.gemstone.gemfire.internal.cache.execute.AbstractExecution;
@@ -62,15 +68,21 @@ import 
com.gemstone.gemfire.management.internal.security.ResourceOperation;
  */
 @SuppressWarnings("unused")
 public class LuceneIndexCommands extends AbstractCommandsSupport {
-
   private static final LuceneCreateIndexFunction createIndexFunction = new 
LuceneCreateIndexFunction();
+  private static final LuceneDescribeIndexFunction describeIndexFunction = new 
LuceneDescribeIndexFunction();
 
   @CliCommand(value = LuceneCliStrings.LUCENE_LIST_INDEX, help = 
LuceneCliStrings.LUCENE_LIST_INDEX__HELP)
   @CliMetaData(shellOnly = false, relatedTopic={CliStrings.TOPIC_GEODE_REGION, 
CliStrings.TOPIC_GEODE_DATA })
   @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ)
-  public Result listIndex() {
+  public Result listIndex(
+    @CliOption(key = LuceneCliStrings.LUCENE_LIST_INDEX__STATS,
+      mandatory=false,
+      specifiedDefaultValue = "true",
+      unspecifiedDefaultValue = "false",
+      help = LuceneCliStrings.LUCENE_LIST_INDEX__STATS__HELP) final boolean 
stats) {
+
     try {
-      return toTabularResult(getIndexListing());
+      return toTabularResult(getIndexListing(),stats);
     }
     catch (FunctionInvocationTargetException ignore) {
       return 
ResultBuilder.createGemFireErrorResult(CliStrings.format(CliStrings.COULD_NOT_EXECUTE_COMMAND_TRY_AGAIN,
@@ -105,7 +117,7 @@ public class LuceneIndexCommands extends 
AbstractCommandsSupport {
       .collect(Collectors.toList());
   }
 
-  protected Result toTabularResult(final List<LuceneIndexDetails> 
indexDetailsList) {
+  protected Result toTabularResult(final List<LuceneIndexDetails> 
indexDetailsList, boolean stats) {
     if (!indexDetailsList.isEmpty()) {
       final TabularResultData indexData = 
ResultBuilder.createTabularResultData();
 
@@ -114,6 +126,13 @@ public class LuceneIndexCommands extends 
AbstractCommandsSupport {
         indexData.accumulate("Region Path", indexDetails.getRegionPath());
         indexData.accumulate("Indexed Fields", 
indexDetails.getSearchableFieldNamesString());
         indexData.accumulate("Field Analyzer", 
indexDetails.getFieldAnalyzersString());
+
+        if (stats==true) {
+          indexData.accumulate("Query 
Executions",indexDetails.getIndexStats().get("queryExecutions"));
+          
indexData.accumulate("Updates",indexDetails.getIndexStats().get("updates"));
+          
indexData.accumulate("Commits",indexDetails.getIndexStats().get("commits"));
+          
indexData.accumulate("Documents",indexDetails.getIndexStats().get("documents"));
+        }
       }
       return ResultBuilder.buildResult(indexData);
     }
@@ -126,11 +145,11 @@ public class LuceneIndexCommands extends 
AbstractCommandsSupport {
   @CliMetaData(shellOnly = false, relatedTopic={CliStrings.TOPIC_GEODE_REGION, 
CliStrings.TOPIC_GEODE_DATA }, writesToSharedConfiguration=true)
   //TODO : Add optionContext for indexName
   public Result createIndex(
-    @CliOption(key = LuceneCliStrings.LUCENE_CREATE_INDEX__NAME,
+    @CliOption(key = LuceneCliStrings.LUCENE__INDEX_NAME,
       mandatory=true,
       help = LuceneCliStrings.LUCENE_CREATE_INDEX__NAME__HELP) final String 
indexName,
 
-    @CliOption (key = LuceneCliStrings.LUCENE_CREATE_INDEX__REGION,
+    @CliOption (key = LuceneCliStrings.LUCENE__REGION_PATH,
       mandatory = true,
       optionContext = ConverterHint.REGIONPATH,
       help = LuceneCliStrings.LUCENE_CREATE_INDEX__REGION_HELP) final String 
regionPath,
@@ -159,7 +178,7 @@ public class LuceneIndexCommands extends 
AbstractCommandsSupport {
     try {
       final Cache cache = getCache();
       LuceneIndexInfo indexInfo = new LuceneIndexInfo(indexName, regionPath, 
fields, analyzers);
-      final ResultCollector<?, ?> rc = this.createIndexOnGroups(groups, 
indexInfo);
+      final ResultCollector<?, ?> rc = 
this.executeFunctionOnGroups(createIndexFunction, groups, indexInfo);
       final List<CliFunctionResult> funcResults = (List<CliFunctionResult>) 
rc.getResult();
 
       final Set<String> successfulMembers = new TreeSet<String>();
@@ -236,8 +255,49 @@ public class LuceneIndexCommands extends 
AbstractCommandsSupport {
     return result;
   }
 
-  protected ResultCollector<?, ?> createIndexOnGroups( String[] groups, final 
LuceneIndexInfo indexInfo) throws CommandResultException {
+  @CliCommand(value = LuceneCliStrings.LUCENE_DESCRIBE_INDEX, help = 
LuceneCliStrings.LUCENE_DESCRIBE_INDEX__HELP)
+  @CliMetaData(shellOnly = false, relatedTopic={CliStrings.TOPIC_GEODE_REGION, 
CliStrings.TOPIC_GEODE_DATA })
+  @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ)
+  public Result describeIndex(
+    @CliOption(key = LuceneCliStrings.LUCENE__INDEX_NAME,
+      mandatory=true,
+      help = LuceneCliStrings.LUCENE_DESCRIBE_INDEX__NAME__HELP) final String 
indexName,
+
+    @CliOption (key = LuceneCliStrings.LUCENE__REGION_PATH,
+      mandatory = true,
+      optionContext = ConverterHint.REGIONPATH,
+      help = LuceneCliStrings.LUCENE_DESCRIBE_INDEX__REGION_HELP) final String 
regionPath) {
+    try {
+      LuceneIndexInfo indexInfo = new LuceneIndexInfo(indexName, regionPath);
+      return toTabularResult(getIndexDetails(indexInfo),true);
+    }
+    catch (FunctionInvocationTargetException ignore) {
+      return 
ResultBuilder.createGemFireErrorResult(CliStrings.format(CliStrings.COULD_NOT_EXECUTE_COMMAND_TRY_AGAIN,
+        LuceneCliStrings.LUCENE_DESCRIBE_INDEX));
+    }
+    catch (VirtualMachineError e) {
+      SystemFailure.initiateFailure(e);
+      throw e;
+    }
+    catch (Throwable t) {
+      SystemFailure.checkFailure();
+      getCache().getLogger().error(t);
+      return 
ResultBuilder.createGemFireErrorResult(String.format(LuceneCliStrings.LUCENE_DESCRIBE_INDEX__ERROR_MESSAGE,
+        toString(t, isDebugging())));
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  protected List<LuceneIndexDetails> getIndexDetails(LuceneIndexInfo 
indexInfo) throws Exception {
+    GeodeSecurityUtil.authorizeRegionManage(indexInfo.getRegionPath());
+    final String[] groups = {};
+    final ResultCollector<?, ?> rc = 
this.executeFunctionOnGroups(describeIndexFunction, groups, indexInfo);
+    final List<LuceneIndexDetails> funcResults = (List<LuceneIndexDetails>) 
rc.getResult();
+    return funcResults.stream().filter(indexDetails -> indexDetails != 
null).collect(Collectors.toList());
+  }
+
+  protected ResultCollector<?, ?> executeFunctionOnGroups(FunctionAdapter 
function, String[]groups, final LuceneIndexInfo indexInfo) throws 
CommandResultException {
     final Set<DistributedMember> targetMembers = 
CliUtil.findAllMatchingMembers(groups, null);
-    return CliUtil.executeFunction(createIndexFunction, indexInfo, 
targetMembers);
+    return CliUtil.executeFunction(function, indexInfo, targetMembers);
   }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/ce0b7e7d/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexDetails.java
----------------------------------------------------------------------
diff --git 
a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexDetails.java
 
b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexDetails.java
index c967530..7526425 100644
--- 
a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexDetails.java
+++ 
b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexDetails.java
@@ -22,7 +22,9 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
+
 import com.gemstone.gemfire.cache.lucene.internal.LuceneIndexImpl;
+import com.gemstone.gemfire.cache.lucene.internal.LuceneIndexStats;
 
 import org.apache.lucene.analysis.Analyzer;
 
@@ -33,16 +35,35 @@ public class LuceneIndexDetails implements 
Comparable<LuceneIndexDetails>, Seria
   private final String regionPath;
   private final String[] searchableFieldNames;
   private final Map<String, String> fieldAnalyzers;
+  private final Map<String,Integer> indexStats;
 
-  public LuceneIndexDetails(final String indexName, final String regionPath, 
final String[] searchableFieldNames, Map<String, Analyzer> fieldAnalyzers) {
+  public LuceneIndexDetails(final String indexName, final String regionPath, 
final String[] searchableFieldNames, Map<String, Analyzer> fieldAnalyzers, 
LuceneIndexStats indexStats) {
     this.indexName = indexName;
     this.regionPath = regionPath;
     this.searchableFieldNames = searchableFieldNames;
     this.fieldAnalyzers = getAnalyzerStrings(fieldAnalyzers);
+    this.indexStats=getIndexStatsMap(indexStats);
   }
 
   public LuceneIndexDetails(LuceneIndexImpl index) {
-    this(index.getName(), index.getRegionPath(), index.getFieldNames(), 
index.getFieldAnalyzers());
+    this(index.getName(), index.getRegionPath(), index.getFieldNames(), 
index.getFieldAnalyzers(),index.getIndexStats());
+  }
+
+  public Map<String,Integer> getIndexStats() {
+    return indexStats;
+  }
+  private  Map<String,Integer> getIndexStatsMap(LuceneIndexStats indexStats) {
+    Map<String,Integer> statsMap = new HashMap<>();
+    if (indexStats==null) return statsMap;
+    statsMap.put("queryExecutions",indexStats.getQueryExecutions());
+    statsMap.put("updates",indexStats.getUpdates());
+    statsMap.put("commits",indexStats.getCommits());
+    statsMap.put("documents",indexStats.getDocuments());
+    return statsMap;
+  }
+
+  public String getIndexStatsString() {
+    return indexStats.toString();
   }
 
   private Map<String, String> getAnalyzerStrings(Map<String, Analyzer> 
fieldAnalyzers) {
@@ -77,6 +98,7 @@ public class LuceneIndexDetails implements 
Comparable<LuceneIndexDetails>, Seria
     buffer.append(",\tRegion Path = "+regionPath);
     buffer.append(",\tIndexed Fields = "+getSearchableFieldNamesString());
     buffer.append(",\tField Analyzer = "+getFieldAnalyzersString());
+    buffer.append(",\tIndex Statistics =\n\t"+getIndexStatsString());
     buffer.append("\n}\n");
     return buffer.toString();
   }
@@ -90,10 +112,6 @@ public class LuceneIndexDetails implements 
Comparable<LuceneIndexDetails>, Seria
     return regionPath;
   }
 
-  public String[] getSearchableFieldNames() {
-    return searchableFieldNames;
-  }
-
   private static <T extends Comparable<T>> int compare(final T obj1, final T 
obj2) {
     return (obj1 == null && obj2 == null ? 0 : (obj1 == null ? 1 : (obj2 == 
null ? -1 : obj1.compareTo(obj2))));
   }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/ce0b7e7d/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexInfo.java
----------------------------------------------------------------------
diff --git 
a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexInfo.java
 
b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexInfo.java
index 76b7b60..3df292c 100644
--- 
a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexInfo.java
+++ 
b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexInfo.java
@@ -41,6 +41,10 @@ public class LuceneIndexInfo implements Serializable {
     this.fieldAnalyzers = fieldAnalyzers;
   }
 
+  public LuceneIndexInfo(final String indexName, final String regionPath) {
+    this(indexName,regionPath,null,null);
+  }
+
   public String getIndexName() {
     return indexName;
   }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/ce0b7e7d/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneDescribeIndexFunction.java
----------------------------------------------------------------------
diff --git 
a/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneDescribeIndexFunction.java
 
b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneDescribeIndexFunction.java
new file mode 100755
index 0000000..b91db60
--- /dev/null
+++ 
b/geode-lucene/src/main/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneDescribeIndexFunction.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 com.gemstone.gemfire.cache.lucene.internal.cli.functions;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.execute.FunctionAdapter;
+import com.gemstone.gemfire.cache.execute.FunctionContext;
+import com.gemstone.gemfire.cache.lucene.LuceneIndex;
+import com.gemstone.gemfire.cache.lucene.LuceneService;
+import com.gemstone.gemfire.cache.lucene.LuceneServiceProvider;
+import com.gemstone.gemfire.cache.lucene.internal.LuceneIndexImpl;
+import com.gemstone.gemfire.cache.lucene.internal.cli.LuceneIndexDetails;
+import com.gemstone.gemfire.cache.lucene.internal.cli.LuceneIndexInfo;
+import com.gemstone.gemfire.internal.InternalEntity;
+
+/**
+ * The LuceneDescribeIndexFunction class is a function used to collect the 
information on a particular lucene index.
+ * </p>
+ * @see Cache
+ * @see com.gemstone.gemfire.cache.execute.Function
+ * @see FunctionAdapter
+ * @see FunctionContext
+ * @see InternalEntity
+ * @see LuceneIndexDetails
+ * @see LuceneIndexInfo
+ */
+@SuppressWarnings("unused")
+public class LuceneDescribeIndexFunction extends FunctionAdapter implements 
InternalEntity {
+
+  protected Cache getCache() {
+    return CacheFactory.getAnyInstance();
+  }
+
+  public String getId() {
+    return LuceneDescribeIndexFunction.class.getName();
+  }
+
+  public void execute(final FunctionContext context) {
+    LuceneIndexDetails result = null;
+    final Cache cache = getCache();
+    final LuceneIndexInfo indexInfo = (LuceneIndexInfo) context.getArguments();
+    LuceneService service = LuceneServiceProvider.get(cache);
+    LuceneIndex index = service.getIndex(indexInfo.getIndexName(), 
indexInfo.getRegionPath());
+    if (index != null) {
+      result = new LuceneIndexDetails((LuceneIndexImpl) index);
+    }
+    context.getResultSender().lastResult(result);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/ce0b7e7d/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsDUnitTest.java
----------------------------------------------------------------------
diff --git 
a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsDUnitTest.java
 
b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsDUnitTest.java
index 2647bcc..06cc410 100755
--- 
a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsDUnitTest.java
+++ 
b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsDUnitTest.java
@@ -28,7 +28,6 @@ import 
com.gemstone.gemfire.management.internal.cli.result.CommandResult;
 import com.gemstone.gemfire.management.internal.cli.util.CommandStringBuilder;
 import com.gemstone.gemfire.test.dunit.*;
 import com.gemstone.gemfire.test.junit.categories.DistributedTest;
-import com.sun.org.apache.regexp.internal.RE;
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.core.KeywordAnalyzer;
@@ -45,7 +44,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
-import java.util.stream.Collectors;
 
 @Category(DistributedTest.class)
 public class LuceneIndexCommandsDUnitTest extends CliCommandTestBase {
@@ -57,15 +55,41 @@ public class LuceneIndexCommandsDUnitTest extends 
CliCommandTestBase {
   }
 
   @Test
-  public void listIndexShouldReturnExistingIndex() throws Exception {
+  public void listIndexShouldReturnExistingIndexWithStats() throws Exception {
     final VM vm1 = Host.getHost(0).getVM(1);
 
     createIndex(vm1);
     CommandManager.getInstance().add(LuceneIndexCommands.class.newInstance());
 
     CommandStringBuilder csb = new 
CommandStringBuilder(LuceneCliStrings.LUCENE_LIST_INDEX);
+    csb.addOption(LuceneCliStrings.LUCENE_LIST_INDEX__STATS,"true");
     String resultAsString = executeCommandAndLogResult(csb);
     assertTrue(resultAsString.contains(INDEX_NAME));
+    assertTrue(resultAsString.contains("Documents"));
+  }
+
+  @Test
+  public void listIndexShouldReturnExistingIndexWithoutStats() throws 
Exception {
+    final VM vm1 = Host.getHost(0).getVM(1);
+
+    createIndex(vm1);
+    CommandManager.getInstance().add(LuceneIndexCommands.class.newInstance());
+
+    CommandStringBuilder csb = new 
CommandStringBuilder(LuceneCliStrings.LUCENE_LIST_INDEX);
+    String resultAsString = executeCommandAndLogResult(csb);
+    assertTrue(resultAsString.contains(INDEX_NAME));
+    assertFalse(resultAsString.contains("Documents"));
+  }
+
+  @Test
+  public void listIndexWhenNoExistingIndexShouldReturnNoIndex() throws 
Exception {
+    final VM vm1 = Host.getHost(0).getVM(1);
+
+    CommandManager.getInstance().add(LuceneIndexCommands.class.newInstance());
+
+    CommandStringBuilder csb = new 
CommandStringBuilder(LuceneCliStrings.LUCENE_LIST_INDEX);
+    String resultAsString = executeCommandAndLogResult(csb);
+    assertTrue(resultAsString.contains("No lucene indexes found"));
   }
 
   @Test
@@ -76,8 +100,8 @@ public class LuceneIndexCommandsDUnitTest extends 
CliCommandTestBase {
     CommandManager.getInstance().add(LuceneIndexCommands.class.newInstance());
 
     CommandStringBuilder csb = new 
CommandStringBuilder(LuceneCliStrings.LUCENE_CREATE_INDEX);
-    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__NAME,INDEX_NAME);
-    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__REGION,REGION_NAME);
+    csb.addOption(LuceneCliStrings.LUCENE__INDEX_NAME,INDEX_NAME);
+    csb.addOption(LuceneCliStrings.LUCENE__REGION_PATH,REGION_NAME);
     
csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__FIELD,"field1,field2,field3");
 
     String resultAsString = executeCommandAndLogResult(csb);
@@ -104,8 +128,8 @@ public class LuceneIndexCommandsDUnitTest extends 
CliCommandTestBase {
 
 
     CommandStringBuilder csb = new 
CommandStringBuilder(LuceneCliStrings.LUCENE_CREATE_INDEX);
-    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__NAME,INDEX_NAME);
-    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__REGION,REGION_NAME);
+    csb.addOption(LuceneCliStrings.LUCENE__INDEX_NAME,INDEX_NAME);
+    csb.addOption(LuceneCliStrings.LUCENE__REGION_PATH,REGION_NAME);
     
csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__FIELD,"field1,field2,field3");
     
csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__ANALYZER,String.join(",",analyzerNames));
 
@@ -136,12 +160,11 @@ public class LuceneIndexCommandsDUnitTest extends 
CliCommandTestBase {
       getCache();
     });
 
-
     CommandManager.getInstance().add(LuceneIndexCommands.class.newInstance());
 
     CommandStringBuilder csb = new 
CommandStringBuilder(LuceneCliStrings.LUCENE_CREATE_INDEX);
-    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__NAME,INDEX_NAME);
-    csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__REGION,REGION_NAME);
+    csb.addOption(LuceneCliStrings.LUCENE__INDEX_NAME,INDEX_NAME);
+    csb.addOption(LuceneCliStrings.LUCENE__REGION_PATH,REGION_NAME);
     
csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__FIELD,"field1,field2,field3");
     csb.addOption(LuceneCliStrings.LUCENE_CREATE_INDEX__GROUP,"group1");
     String resultAsString = executeCommandAndLogResult(csb);
@@ -164,6 +187,35 @@ public class LuceneIndexCommandsDUnitTest extends 
CliCommandTestBase {
     });
   }
 
+  @Test
+  public void describeIndexShouldReturnExistingIndex() throws Exception {
+    final VM vm1 = Host.getHost(0).getVM(1);
+
+    createIndex(vm1);
+    CommandManager.getInstance().add(LuceneIndexCommands.class.newInstance());
+
+    CommandStringBuilder csb = new 
CommandStringBuilder(LuceneCliStrings.LUCENE_DESCRIBE_INDEX);
+    csb.addOption(LuceneCliStrings.LUCENE__INDEX_NAME,INDEX_NAME);
+    csb.addOption(LuceneCliStrings.LUCENE__REGION_PATH,REGION_NAME);
+    String resultAsString = executeCommandAndLogResult(csb);
+    assertTrue(resultAsString.contains(INDEX_NAME));
+  }
+
+  @Test
+  public void describeIndexShouldNotReturnResultWhenIndexNotFound() throws 
Exception {
+    final VM vm1 = Host.getHost(0).getVM(1);
+
+    createIndex(vm1);
+    CommandManager.getInstance().add(LuceneIndexCommands.class.newInstance());
+
+    CommandStringBuilder csb = new 
CommandStringBuilder(LuceneCliStrings.LUCENE_DESCRIBE_INDEX);
+    csb.addOption(LuceneCliStrings.LUCENE__INDEX_NAME,"notAnIndex");
+    csb.addOption(LuceneCliStrings.LUCENE__REGION_PATH,REGION_NAME);
+    String resultAsString = executeCommandAndLogResult(csb);
+
+    assertTrue(resultAsString.contains("No lucene indexes found"));
+  }
+
   private void createRegion() {
     
getCache().createRegionFactory(RegionShortcut.PARTITION).create(REGION_NAME);
   }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/ce0b7e7d/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsJUnitTest.java
----------------------------------------------------------------------
diff --git 
a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsJUnitTest.java
 
b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsJUnitTest.java
index 0ebfa10..41f1ca4 100644
--- 
a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsJUnitTest.java
+++ 
b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/LuceneIndexCommandsJUnitTest.java
@@ -38,6 +38,9 @@ import org.junit.experimental.categories.Category;
 import com.gemstone.gemfire.cache.Cache;
 import com.gemstone.gemfire.cache.execute.Execution;
 import com.gemstone.gemfire.cache.execute.ResultCollector;
+import com.gemstone.gemfire.cache.lucene.internal.LuceneIndexStats;
+import 
com.gemstone.gemfire.cache.lucene.internal.cli.functions.LuceneCreateIndexFunction;
+import 
com.gemstone.gemfire.cache.lucene.internal.cli.functions.LuceneDescribeIndexFunction;
 import 
com.gemstone.gemfire.cache.lucene.internal.cli.functions.LuceneListIndexFunction;
 import com.gemstone.gemfire.distributed.DistributedMember;
 import com.gemstone.gemfire.internal.cache.execute.AbstractExecution;
@@ -45,6 +48,7 @@ import com.gemstone.gemfire.internal.util.CollectionUtils;
 import com.gemstone.gemfire.management.cli.Result;
 import com.gemstone.gemfire.management.cli.Result.Status;
 import 
com.gemstone.gemfire.management.internal.cli.functions.CliFunctionResult;
+import 
com.gemstone.gemfire.management.internal.cli.functions.CreateIndexFunction;
 import com.gemstone.gemfire.management.internal.cli.i18n.CliStrings;
 import com.gemstone.gemfire.management.internal.cli.result.CommandResult;
 import 
com.gemstone.gemfire.management.internal.cli.result.CommandResultException;
@@ -70,16 +74,8 @@ import com.gemstone.gemfire.test.junit.categories.UnitTest;
 @Category(UnitTest.class)
 public class LuceneIndexCommandsJUnitTest {
 
-  private LuceneIndexCommands createIndexCommands(final Cache cache, final 
Execution functionExecutor) {
-    return new LuceneTestIndexCommands(cache, functionExecutor);
-  }
-
-  private LuceneIndexDetails createIndexDetails(final String indexName, final 
String regionPath, final String[] searchableFields, final Map<String, Analyzer> 
fieldAnalyzers) {
-    return new LuceneIndexDetails(indexName, regionPath, searchableFields, 
fieldAnalyzers);
-  }
-
   @Test
-  public void testListIndex() {
+  public void testListIndexWithoutStats() {
 
     final Cache mockCache = mock(Cache.class, "Cache");
     final AbstractExecution mockFunctionExecutor = 
mock(AbstractExecution.class, "Function Executor");
@@ -112,7 +108,7 @@ public class LuceneIndexCommandsJUnitTest {
 
     final LuceneIndexCommands commands = createIndexCommands(mockCache, 
mockFunctionExecutor);
 
-    CommandResult result = (CommandResult) commands.listIndex();
+    CommandResult result = (CommandResult) commands.listIndex(false);
     TabularResultData data = (TabularResultData) result.getResultData();
     assertEquals(Arrays.asList("memberFive", "memberSix", "memberTen"), 
data.retrieveAllValues("Index Name"));
     assertEquals(Arrays.asList("/Employees", "/Employees", "/Employees"), 
data.retrieveAllValues("Region Path"));
@@ -121,6 +117,53 @@ public class LuceneIndexCommandsJUnitTest {
   }
 
   @Test
+  public void testListIndexWithStats() {
+
+    final Cache mockCache = mock(Cache.class, "Cache");
+    final AbstractExecution mockFunctionExecutor = 
mock(AbstractExecution.class, "Function Executor");
+    final ResultCollector mockResultCollector = mock(ResultCollector.class, 
"ResultCollector");
+    final LuceneIndexStats mockIndexStats1=getMockIndexStats(1,10,5,1);
+    final LuceneIndexStats mockIndexStats2=getMockIndexStats(2,20,10,2);
+    final LuceneIndexStats mockIndexStats3=getMockIndexStats(3,30,15,3);
+    String[] searchableFields={"field1","field2","field3"};
+    Map<String, Analyzer> fieldAnalyzers = new HashMap<>();
+    fieldAnalyzers.put("field1", new StandardAnalyzer());
+    fieldAnalyzers.put("field2", new KeywordAnalyzer());
+    fieldAnalyzers.put("field3", null);
+    final LuceneIndexDetails indexDetails1 = createIndexDetails("memberFive", 
"/Employees", searchableFields, fieldAnalyzers,mockIndexStats1);
+    final LuceneIndexDetails indexDetails2 = createIndexDetails("memberSix", 
"/Employees", searchableFields, fieldAnalyzers,mockIndexStats2);
+    final LuceneIndexDetails indexDetails3 = createIndexDetails("memberTen", 
"/Employees", searchableFields, fieldAnalyzers,mockIndexStats3);
+
+
+    final List<LuceneIndexDetails> expectedIndexDetails = new ArrayList<>(3);
+    expectedIndexDetails.add(indexDetails1);
+    expectedIndexDetails.add(indexDetails2);
+    expectedIndexDetails.add(indexDetails3);
+
+    final List<Set<LuceneIndexDetails>> results = new ArrayList<>();
+
+    results.add(CollectionUtils.asSet(indexDetails2, 
indexDetails1,indexDetails3));
+
+    when(mockFunctionExecutor.execute(isA(LuceneListIndexFunction.class)))
+      .thenReturn(mockResultCollector);
+    when(mockResultCollector.getResult())
+      .thenReturn(results);
+
+    final LuceneIndexCommands commands = createIndexCommands(mockCache, 
mockFunctionExecutor);
+
+    CommandResult result = (CommandResult) commands.listIndex(true);
+    TabularResultData data = (TabularResultData) result.getResultData();
+    assertEquals(Arrays.asList("memberFive", "memberSix", "memberTen"), 
data.retrieveAllValues("Index Name"));
+    assertEquals(Arrays.asList("/Employees", "/Employees", "/Employees"), 
data.retrieveAllValues("Region Path"));
+    assertEquals(Arrays.asList("[field1, field2, field3]", "[field1, field2, 
field3]", "[field1, field2, field3]"), data.retrieveAllValues("Indexed 
Fields"));
+    assertEquals(Arrays.asList("{field1=StandardAnalyzer, 
field2=KeywordAnalyzer}", "{field1=StandardAnalyzer, field2=KeywordAnalyzer}", 
"{field1=StandardAnalyzer, field2=KeywordAnalyzer}"), 
data.retrieveAllValues("Field Analyzer"));
+    assertEquals(Arrays.asList("1","2","3"), data.retrieveAllValues("Query 
Executions"));
+    assertEquals(Arrays.asList("10","20","30"), 
data.retrieveAllValues("Commits"));
+    assertEquals(Arrays.asList("5","10","15"), 
data.retrieveAllValues("Updates"));
+    assertEquals(Arrays.asList("1","2","3"), 
data.retrieveAllValues("Documents"));
+  }
+
+  @Test
   public void testCreateIndex() throws CommandResultException {
     final Cache mockCache=mock(Cache.class);
     final ResultCollector mockResultCollector = mock(ResultCollector.class);
@@ -129,7 +172,7 @@ public class LuceneIndexCommandsJUnitTest {
     final List<CliFunctionResult> cliFunctionResults=new ArrayList<>();
     cliFunctionResults.add(new CliFunctionResult(memberId,true,"Index 
Created"));
 
-    
doReturn(mockResultCollector).when(commands).createIndexOnGroups(any(),any(LuceneIndexInfo.class));
+    
doReturn(mockResultCollector).when(commands).executeFunctionOnGroups(isA(LuceneCreateIndexFunction.class),any(),any(LuceneIndexInfo.class));
     doReturn(cliFunctionResults).when(mockResultCollector).getResult();
 
     String indexName ="index";
@@ -153,6 +196,65 @@ public class LuceneIndexCommandsJUnitTest {
     return ResultBuilder.buildResult(infoResult);
   }
 
+  @Test
+  public void testDescribeIndex() throws CommandResultException {
+
+    final Cache mockCache = mock(Cache.class, "Cache");
+    final ResultCollector mockResultCollector = mock(ResultCollector.class, 
"ResultCollector");
+    final LuceneIndexCommands 
commands=spy(createIndexCommands(mockCache,null));
+
+    String[] searchableFields={"field1","field2","field3"};
+    Map<String, Analyzer> fieldAnalyzers = new HashMap<>();
+    fieldAnalyzers.put("field1", new StandardAnalyzer());
+    fieldAnalyzers.put("field2", new KeywordAnalyzer());
+    fieldAnalyzers.put("field3", null);
+    final LuceneIndexStats mockIndexStats=getMockIndexStats(1,10,5,1);
+    final List<LuceneIndexDetails> indexDetails = new ArrayList<>();
+    indexDetails.add(createIndexDetails("memberFive", "/Employees", 
searchableFields, fieldAnalyzers,mockIndexStats));
+
+    
doReturn(mockResultCollector).when(commands).executeFunctionOnGroups(isA(LuceneDescribeIndexFunction.class),any(),any(LuceneIndexInfo.class));
+    doReturn(indexDetails).when(mockResultCollector).getResult();
+
+    CommandResult result = (CommandResult) 
commands.describeIndex("memberFive","/Employees");
+
+    TabularResultData data = (TabularResultData) result.getResultData();
+    assertEquals(Arrays.asList("memberFive"), data.retrieveAllValues("Index 
Name"));
+    assertEquals(Arrays.asList("/Employees"), data.retrieveAllValues("Region 
Path"));
+    assertEquals(Arrays.asList("[field1, field2, field3]"), 
data.retrieveAllValues("Indexed Fields"));
+    assertEquals(Arrays.asList("{field1=StandardAnalyzer, 
field2=KeywordAnalyzer}"), data.retrieveAllValues("Field Analyzer"));
+    assertEquals(Arrays.asList("1"), data.retrieveAllValues("Query 
Executions"));
+    assertEquals(Arrays.asList("10"), data.retrieveAllValues("Commits"));
+    assertEquals(Arrays.asList("5"), data.retrieveAllValues("Updates"));
+    assertEquals(Arrays.asList("1"), data.retrieveAllValues("Documents"));
+
+  }
+
+
+  private LuceneIndexStats getMockIndexStats(int queries, int commits, int 
updates, int docs) {
+    LuceneIndexStats mockIndexStats=mock(LuceneIndexStats.class);
+    when(mockIndexStats.getQueryExecutions())
+      .thenReturn(queries);
+    when(mockIndexStats.getCommits())
+      .thenReturn(commits);
+    when(mockIndexStats.getUpdates())
+      .thenReturn(updates);
+    when(mockIndexStats.getDocuments())
+      .thenReturn(docs);
+    return mockIndexStats;
+  }
+
+  private LuceneIndexCommands createIndexCommands(final Cache cache, final 
Execution functionExecutor) {
+    return new LuceneTestIndexCommands(cache, functionExecutor);
+  }
+
+  private LuceneIndexDetails createIndexDetails(final String indexName, final 
String regionPath, final String[] searchableFields, final Map<String, Analyzer> 
fieldAnalyzers, LuceneIndexStats indexStats) {
+    return new LuceneIndexDetails(indexName, regionPath, searchableFields, 
fieldAnalyzers,indexStats);
+  }
+
+  private LuceneIndexDetails createIndexDetails(final String indexName, final 
String regionPath, final String[] searchableFields, final Map<String, Analyzer> 
fieldAnalyzers) {
+    return new LuceneIndexDetails(indexName, regionPath, searchableFields, 
fieldAnalyzers,null);
+  }
+
   private static class LuceneTestIndexCommands extends LuceneIndexCommands {
 
     private final Cache cache;

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/ce0b7e7d/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneDescribeIndexFunctionJUnitTest.java
----------------------------------------------------------------------
diff --git 
a/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneDescribeIndexFunctionJUnitTest.java
 
b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneDescribeIndexFunctionJUnitTest.java
new file mode 100644
index 0000000..3669b90
--- /dev/null
+++ 
b/geode-lucene/src/test/java/com/gemstone/gemfire/cache/lucene/internal/cli/functions/LuceneDescribeIndexFunctionJUnitTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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 com.gemstone.gemfire.cache.lucene.internal.cli.functions;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.gemstone.gemfire.cache.execute.FunctionContext;
+import com.gemstone.gemfire.cache.execute.ResultSender;
+import com.gemstone.gemfire.cache.lucene.LuceneIndex;
+import com.gemstone.gemfire.cache.lucene.internal.InternalLuceneService;
+import com.gemstone.gemfire.cache.lucene.internal.LuceneIndexImpl;
+import com.gemstone.gemfire.cache.lucene.internal.cli.LuceneIndexDetails;
+import com.gemstone.gemfire.cache.lucene.internal.cli.LuceneIndexInfo;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.test.fake.Fakes;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.core.KeywordAnalyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+@Category(UnitTest.class)
+
+public class LuceneDescribeIndexFunctionJUnitTest {
+  
+  @Test
+  @SuppressWarnings("unchecked")
+  public void testExecute() throws Throwable {
+    GemFireCacheImpl cache = Fakes.cache();
+    InternalLuceneService service = mock(InternalLuceneService.class);
+    when(cache.getService(InternalLuceneService.class)).thenReturn(service);
+    FunctionContext context = mock(FunctionContext.class);
+    ResultSender resultSender = mock(ResultSender.class);
+    LuceneIndexInfo indexInfo=getMockLuceneInfo("index1");
+    LuceneIndexImpl index1 = getMockLuceneIndex("index1");
+    LuceneDescribeIndexFunction function = 
spy(LuceneDescribeIndexFunction.class);
+
+    doReturn(indexInfo).when(context).getArguments();
+    doReturn(resultSender).when(context).getResultSender();
+    doReturn(cache).when(function).getCache();
+    
when(service.getIndex(indexInfo.getIndexName(),indexInfo.getRegionPath())).thenReturn(index1);
+
+    function.execute(context);
+    ArgumentCaptor<LuceneIndexDetails> resultCaptor  = 
ArgumentCaptor.forClass(LuceneIndexDetails.class);
+    verify(resultSender).lastResult(resultCaptor.capture());
+    LuceneIndexDetails result = resultCaptor.getValue();
+    LuceneIndexDetails expected=new LuceneIndexDetails(index1);
+
+    assertEquals(expected.getIndexName(),result.getIndexName());
+    assertEquals(expected.getRegionPath(),result.getRegionPath());
+    assertEquals(expected.getIndexStats(),result.getIndexStats());
+    
assertEquals(expected.getFieldAnalyzersString(),result.getFieldAnalyzersString());
+    
assertEquals(expected.getSearchableFieldNamesString(),result.getSearchableFieldNamesString());
+  }
+
+  private LuceneIndexInfo getMockLuceneInfo(final String index1) {
+    LuceneIndexInfo mockInfo=mock(LuceneIndexInfo.class);
+    doReturn(index1).when(mockInfo).getIndexName();
+    doReturn("/region").when(mockInfo).getRegionPath();
+    return mockInfo;
+  }
+
+  private LuceneIndexImpl getMockLuceneIndex(final String indexName)
+  {
+    String[] searchableFields={"field1","field2"};
+    Map<String, Analyzer> fieldAnalyzers = new HashMap<>();
+    fieldAnalyzers.put("field1", new StandardAnalyzer());
+    fieldAnalyzers.put("field2", new KeywordAnalyzer());
+
+    LuceneIndexImpl index = mock(LuceneIndexImpl.class);
+    when(index.getName()).thenReturn(indexName);
+    when(index.getRegionPath()).thenReturn("/region");
+    when(index.getFieldNames()).thenReturn(searchableFields);
+    when(index.getFieldAnalyzers()).thenReturn(fieldAnalyzers);
+    return index;
+  }
+
+}


Reply via email to