/*
 * 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.cache.lucene.internal.cli;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.Arrays;
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 junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.KeywordAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;

import org.apache.geode.cache.execute.Execution;
import org.apache.geode.cache.execute.ResultCollector;
import org.apache.geode.cache.lucene.LuceneSerializer;
import org.apache.geode.cache.lucene.internal.LuceneIndexStats;
import org.apache.geode.cache.lucene.internal.cli.functions.LuceneCreateIndexFunction;
import org.apache.geode.cache.lucene.internal.cli.functions.LuceneDescribeIndexFunction;
import org.apache.geode.cache.lucene.internal.cli.functions.LuceneDestroyIndexFunction;
import org.apache.geode.cache.lucene.internal.cli.functions.LuceneListIndexFunction;
import org.apache.geode.cache.lucene.internal.repository.serializer.HeterogeneousLuceneSerializer;
import org.apache.geode.cache.lucene.internal.repository.serializer.PrimitiveSerializer;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.execute.AbstractExecution;
import org.apache.geode.internal.security.SecurityService;
import org.apache.geode.internal.serialization.Version;
import org.apache.geode.internal.util.CollectionUtils;
import org.apache.geode.management.cli.Result.Status;
import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
import org.apache.geode.management.internal.cli.result.CommandResult;
import org.apache.geode.management.internal.cli.result.model.ResultModel;
import org.apache.geode.management.internal.cli.result.model.TabularResultModel;
import org.apache.geode.management.internal.cli.shell.Gfsh;
import org.apache.geode.test.junit.categories.LuceneTest;

/**
 * The LuceneIndexCommandsJUnitTest class is a test suite of test cases testing the contract and
 * functionality of the Lucene Index Commands.
 *
 * @see LuceneCreateIndexCommand
 * @see LuceneDescribeIndexCommand
 * @see LuceneDestroyIndexCommand
 * @see LuceneListIndexCommand
 * @see LuceneSearchIndexCommand
 */
@Category(LuceneTest.class)
@RunWith(JUnitParamsRunner.class)
public class LuceneIndexCommandsJUnitTest {

  private InternalCache mockCache;

  @Before
  public void before() {
    this.mockCache = mock(InternalCache.class, "InternalCache");
    when(this.mockCache.getSecurityService()).thenReturn(mock(SecurityService.class));
  }

  @Test
  public void testListIndexWithoutStats() {
    final String serverName = "mockServer";
    final AbstractExecution mockFunctionExecutor =
        mock(AbstractExecution.class, "Function Executor");
    final ResultCollector mockResultCollector = mock(ResultCollector.class, "ResultCollector");

    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);
    LuceneSerializer serializer = new HeterogeneousLuceneSerializer();
    final LuceneIndexDetails indexDetails1 = createIndexDetails("memberFive", "/Employees",
        searchableFields, fieldAnalyzers, LuceneIndexStatus.INITIALIZED, serverName, serializer);
    final LuceneIndexDetails indexDetails2 =
        createIndexDetails("memberSix", "/Employees", searchableFields, fieldAnalyzers,
            LuceneIndexStatus.NOT_INITIALIZED, serverName, serializer);
    final LuceneIndexDetails indexDetails3 = createIndexDetails("memberTen", "/Employees",
        searchableFields, fieldAnalyzers, LuceneIndexStatus.INITIALIZED, serverName, serializer);

    final List<Set<LuceneIndexDetails>> results = new ArrayList<>();

    results.add(CollectionUtils.asSet(indexDetails2, indexDetails1, indexDetails3));

    when(mockFunctionExecutor.execute(any(LuceneListIndexFunction.class)))
        .thenReturn(mockResultCollector);
    when(mockResultCollector.getResult()).thenReturn(results);

    final LuceneListIndexCommand command =
        new LuceneTestListIndexCommand(this.mockCache, mockFunctionExecutor);

    ResultModel result = command.listIndex(false);
    TabularResultModel data = result.getTableSection("lucene-indexes");
    assertThat(data.getValuesInColumn("Index Name"))
        .isEqualTo(Arrays.asList("memberFive", "memberSix", "memberTen"));
    assertThat(data.getValuesInColumn("Region Path"))
        .isEqualTo(Arrays.asList("/Employees", "/Employees", "/Employees"));
    assertThat(data.getValuesInColumn("Indexed Fields")).isEqualTo(Arrays.asList(
        "[field1, field2, field3]", "[field1, field2, field3]", "[field1, field2, field3]"));
    assertThat(data.getValuesInColumn("Field Analyzer"))
        .isEqualTo(Arrays.asList("{field1=StandardAnalyzer, field2=KeywordAnalyzer}",
            "{field1=StandardAnalyzer, field2=KeywordAnalyzer}",
            "{field1=StandardAnalyzer, field2=KeywordAnalyzer}"));
    assertThat(data.getValuesInColumn("Status"))
        .isEqualTo(Arrays.asList("INITIALIZED", "NOT_INITIALIZED", "INITIALIZED"));
  }

  @Test
  public void testListIndexWithStats() {
    final String serverName = "mockServer";
    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);
    LuceneSerializer serializer = new HeterogeneousLuceneSerializer();
    final LuceneIndexDetails indexDetails1 =
        createIndexDetails("memberFive", "/Employees", searchableFields, fieldAnalyzers,
            mockIndexStats1, LuceneIndexStatus.INITIALIZED, serverName, serializer);
    final LuceneIndexDetails indexDetails2 =
        createIndexDetails("memberSix", "/Employees", searchableFields, fieldAnalyzers,
            mockIndexStats2, LuceneIndexStatus.INITIALIZED, serverName, serializer);
    final LuceneIndexDetails indexDetails3 =
        createIndexDetails("memberTen", "/Employees", searchableFields, fieldAnalyzers,
            mockIndexStats3, LuceneIndexStatus.INITIALIZED, serverName, serializer);

    final List<Set<LuceneIndexDetails>> results = new ArrayList<>();

    results.add(CollectionUtils.asSet(indexDetails2, indexDetails1, indexDetails3));

    when(mockFunctionExecutor.execute(any(LuceneListIndexFunction.class)))
        .thenReturn(mockResultCollector);
    when(mockResultCollector.getResult()).thenReturn(results);

    final LuceneListIndexCommand command =
        new LuceneTestListIndexCommand(this.mockCache, mockFunctionExecutor);

    ResultModel result = command.listIndex(true);
    TabularResultModel data = result.getTableSection("lucene-indexes");
    assertThat(data.getValuesInColumn("Index Name"))
        .isEqualTo(Arrays.asList("memberFive", "memberSix", "memberTen"));
    assertThat(data.getValuesInColumn("Region Path"))
        .isEqualTo(Arrays.asList("/Employees", "/Employees", "/Employees"));
    assertThat(data.getValuesInColumn("Indexed Fields")).isEqualTo(Arrays.asList(
        "[field1, field2, field3]", "[field1, field2, field3]", "[field1, field2, field3]"));
    assertThat(data.getValuesInColumn("Field Analyzer"))
        .isEqualTo(Arrays.asList("{field1=StandardAnalyzer, field2=KeywordAnalyzer}",
            "{field1=StandardAnalyzer, field2=KeywordAnalyzer}",
            "{field1=StandardAnalyzer, field2=KeywordAnalyzer}"));
    assertThat(data.getValuesInColumn("Query Executions")).isEqualTo(Arrays.asList("1", "2", "3"));
    assertThat(data.getValuesInColumn("Commits")).isEqualTo(Arrays.asList("10", "20", "30"));
    assertThat(data.getValuesInColumn("Updates")).isEqualTo(Arrays.asList("5", "10", "15"));
    assertThat(data.getValuesInColumn("Documents")).isEqualTo(Arrays.asList("1", "2", "3"));
    assertThat(data.getValuesInColumn("Serializer"))
        .isEqualTo(Arrays.asList(HeterogeneousLuceneSerializer.class.getSimpleName(),
            HeterogeneousLuceneSerializer.class.getSimpleName(),
            HeterogeneousLuceneSerializer.class.getSimpleName()));
  }

  @Test
  public void testCreateIndex() throws Exception {
    final ResultCollector mockResultCollector = mock(ResultCollector.class);
    final LuceneCreateIndexCommand command =
        spy(new LuceneTestCreateIndexCommand(this.mockCache, null));

    final List<CliFunctionResult> cliFunctionResults = new ArrayList<>();
    cliFunctionResults
        .add(new CliFunctionResult("member1", CliFunctionResult.StatusState.OK, "Index Created"));
    cliFunctionResults.add(new CliFunctionResult("member2", CliFunctionResult.StatusState.ERROR,
        "Index creation failed"));
    cliFunctionResults
        .add(new CliFunctionResult("member3", CliFunctionResult.StatusState.OK, "Index Created"));

    doReturn(mockResultCollector).when(command).executeFunctionOnAllMembers(
        any(LuceneCreateIndexFunction.class), any(LuceneIndexInfo.class));
    doReturn(cliFunctionResults).when(mockResultCollector).getResult();

    String indexName = "index";
    String regionPath = "regionPath";
    String[] searchableFields = {"field1", "field2", "field3"};
    String[] fieldAnalyzers = {StandardAnalyzer.class.getCanonicalName(),
        KeywordAnalyzer.class.getCanonicalName(), StandardAnalyzer.class.getCanonicalName()};

    String serializer = PrimitiveSerializer.class.getCanonicalName();

    ResultModel result = command.createIndex(indexName, regionPath, searchableFields,
        fieldAnalyzers, serializer);
    assertThat(result.getStatus()).isEqualTo(Status.OK);
    TabularResultModel data = result.getTableSection("lucene-indexes");
    assertThat(data.getValuesInColumn("Member"))
        .isEqualTo(Arrays.asList("member1", "member2", "member3"));
    assertThat(data.getValuesInColumn("Status"))
        .isEqualTo(Arrays.asList("Successfully created lucene index",
            "Failed: Index creation failed", "Successfully created lucene index"));
  }

  @Test
  public void testDescribeIndex() throws Exception {
    final String serverName = "mockServer";
    final ResultCollector mockResultCollector = mock(ResultCollector.class, "ResultCollector");
    final LuceneDescribeIndexCommand command =
        spy(new LuceneTestDescribeIndexCommand(this.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<>();
    LuceneSerializer serializer = new HeterogeneousLuceneSerializer();
    indexDetails.add(createIndexDetails("memberFive", "/Employees", searchableFields,
        fieldAnalyzers, mockIndexStats, LuceneIndexStatus.INITIALIZED, serverName, serializer));

    doReturn(mockResultCollector).when(command).executeFunctionOnRegion(
        any(LuceneDescribeIndexFunction.class), any(LuceneIndexInfo.class), eq(true));
    doReturn(indexDetails).when(mockResultCollector).getResult();

    ResultModel result = command.describeIndex("memberFive", "/Employees");

    TabularResultModel data = result.getTableSection("lucene-indexes");
    assertThat(data.getValuesInColumn("Index Name"))
        .isEqualTo(Collections.singletonList("memberFive"));
    assertThat(data.getValuesInColumn("Region Path"))
        .isEqualTo(Collections.singletonList("/Employees"));
    assertThat(data.getValuesInColumn("Indexed Fields"))
        .isEqualTo(Collections.singletonList("[field1, field2, field3]"));
    assertThat(data.getValuesInColumn("Field Analyzer"))
        .isEqualTo(Collections.singletonList("{field1=StandardAnalyzer, field2=KeywordAnalyzer}"));
    assertThat(data.getValuesInColumn("Status"))
        .isEqualTo(Collections.singletonList("INITIALIZED"));
    assertThat(data.getValuesInColumn("Query Executions"))
        .isEqualTo(Collections.singletonList("1"));
    assertThat(data.getValuesInColumn("Commits")).isEqualTo(Collections.singletonList("10"));
    assertThat(data.getValuesInColumn("Updates")).isEqualTo(Collections.singletonList("5"));
    assertThat(data.getValuesInColumn("Documents")).isEqualTo(Collections.singletonList("1"));
  }

  @Test
  public void testSearchIndex() throws Exception {
    final ResultCollector mockResultCollector = mock(ResultCollector.class, "ResultCollector");
    final LuceneSearchIndexCommand command =
        spy(new LuceneTestSearchIndexCommand(this.mockCache, null));

    final List<Set<LuceneSearchResults>> queryResultsList = new ArrayList<>();
    HashSet<LuceneSearchResults> queryResults = new HashSet<>();
    queryResults.add(createQueryResults("A", "Result1", Float.valueOf("1.3")));
    queryResults.add(createQueryResults("B", "Result1", Float.valueOf("1.2")));
    queryResults.add(createQueryResults("C", "Result1", Float.valueOf("1.1")));
    queryResultsList.add(queryResults);
    doReturn(mockResultCollector).when(command).executeSearch(any(LuceneQueryInfo.class));
    doReturn(queryResultsList).when(mockResultCollector).getResult();

    ResultModel result =
        command.searchIndex("index", "region", "Result1", "field1", -1, false);
    TabularResultModel data = result.getTableSection("lucene-indexes");
    assertThat(data.getValuesInColumn("key")).isEqualTo(Arrays.asList("A", "B", "C"));
    assertThat(data.getValuesInColumn("value"))
        .isEqualTo(Arrays.asList("Result1", "Result1", "Result1"));
    assertThat(data.getValuesInColumn("score")).isEqualTo(Arrays.asList("1.3", "1.2", "1.1"));
  }

  @Test
  public void testSearchIndexWithPaging() throws Exception {
    final Gfsh mockGfsh = mock(Gfsh.class);
    final ResultCollector mockResultCollector = mock(ResultCollector.class, "ResultCollector");
    final LuceneSearchIndexCommand command =
        spy(new LuceneTestSearchIndexCommand(this.mockCache, null));
    ArgumentCaptor<String> resultCaptor = ArgumentCaptor.forClass(String.class);

    LuceneSearchResults result1 = createQueryResults("A", "Result1", Float.valueOf("1.7"));
    LuceneSearchResults result2 = createQueryResults("B", "Result1", Float.valueOf("1.6"));
    LuceneSearchResults result3 = createQueryResults("C", "Result1", Float.valueOf("1.5"));
    LuceneSearchResults result4 = createQueryResults("D", "Result1", Float.valueOf("1.4"));
    LuceneSearchResults result5 = createQueryResults("E", "Result1", Float.valueOf("1.3"));
    LuceneSearchResults result6 = createQueryResults("F", "Result1", Float.valueOf("1.2"));
    LuceneSearchResults result7 = createQueryResults("G", "Result1", Float.valueOf("1.1"));
    final List<Set<LuceneSearchResults>> queryResultsList =
        getSearchResults(result1, result2, result3, result4, result5, result6, result7);

    doReturn(mockResultCollector).when(command).executeSearch(any(LuceneQueryInfo.class));
    doReturn(queryResultsList).when(mockResultCollector).getResult();
    doReturn(mockGfsh).when(command).initGfsh();
    when(mockGfsh.interact(anyString())).thenReturn("n").thenReturn("n").thenReturn("n")
        .thenReturn("n").thenReturn("p").thenReturn("p").thenReturn("p").thenReturn("p")
        .thenReturn("p").thenReturn("n").thenReturn("q");
    when(command.getPageSize()).thenReturn(2);

    LuceneSearchResults[] expectedResults =
        new LuceneSearchResults[] {result7, result6, result5, result4, result3, result2, result1};
    String expectedPage1 = getPage(expectedResults, new int[] {6, 5});
    String expectedPage2 = getPage(expectedResults, new int[] {4, 3});
    String expectedPage3 = getPage(expectedResults, new int[] {2, 1});
    String expectedPage4 = getPage(expectedResults, new int[] {0});

    command.searchIndex("index", "region", "Result1", "field1", -1, false);
    verify(mockGfsh, times(20)).printAsInfo(resultCaptor.capture());
    List<String> actualPageResults = resultCaptor.getAllValues();

    assertThat(actualPageResults.get(0)).isEqualTo(expectedPage1);
    assertThat(actualPageResults.get(1)).isEqualTo("\t\tPage 1 of 4");

    assertThat(actualPageResults.get(2)).isEqualTo(expectedPage2);
    assertThat(actualPageResults.get(3)).isEqualTo("\t\tPage 2 of 4");

    assertThat(actualPageResults.get(4)).isEqualTo(expectedPage3);
    assertThat(actualPageResults.get(5)).isEqualTo("\t\tPage 3 of 4");

    assertThat(actualPageResults.get(6)).isEqualTo(expectedPage4);
    assertThat(actualPageResults.get(7)).isEqualTo("\t\tPage 4 of 4");

    assertThat(actualPageResults.get(8)).isEqualTo("No more results to display.");

    assertThat(actualPageResults.get(9)).isEqualTo(expectedPage4);
    assertThat(actualPageResults.get(10)).isEqualTo("\t\tPage 4 of 4");

    assertThat(actualPageResults.get(11)).isEqualTo(expectedPage3);
    assertThat(actualPageResults.get(12)).isEqualTo("\t\tPage 3 of 4");

    assertThat(actualPageResults.get(13)).isEqualTo(expectedPage2);
    assertThat(actualPageResults.get(14)).isEqualTo("\t\tPage 2 of 4");

    assertThat(actualPageResults.get(15)).isEqualTo(expectedPage1);
    assertThat(actualPageResults.get(16)).isEqualTo("\t\tPage 1 of 4");

    assertThat(actualPageResults.get(17)).isEqualTo("At the top of the search results.");

    assertThat(actualPageResults.get(18)).isEqualTo(expectedPage1);
    assertThat(actualPageResults.get(19)).isEqualTo("\t\tPage 1 of 4");
  }

  @Test
  public void testSearchIndexWithKeysOnly() throws Exception {
    final ResultCollector mockResultCollector = mock(ResultCollector.class, "ResultCollector");
    final LuceneSearchIndexCommand command =
        spy(new LuceneTestSearchIndexCommand(this.mockCache, null));

    final List<Set<LuceneSearchResults>> queryResultsList = new ArrayList<>();
    HashSet<LuceneSearchResults> queryResults = new HashSet<>();
    queryResults.add(createQueryResults("A", "Result1", Float.valueOf("1.3")));
    queryResults.add(createQueryResults("B", "Result1", Float.valueOf("1.2")));
    queryResults.add(createQueryResults("C", "Result1", Float.valueOf("1.1")));
    queryResultsList.add(queryResults);
    doReturn(mockResultCollector).when(command).executeSearch(any(LuceneQueryInfo.class));
    doReturn(queryResultsList).when(mockResultCollector).getResult();

    ResultModel result = command.searchIndex("index", "region", "Result1", "field1", -1, true);
    TabularResultModel data = result.getTableSection("lucene-indexes");
    assertThat(data.getValuesInColumn("key")).isEqualTo(Arrays.asList("A", "B", "C"));
  }

  @Test
  public void testSearchIndexWhenSearchResultsHaveSameScore() throws Exception {
    final ResultCollector mockResultCollector = mock(ResultCollector.class, "ResultCollector");
    final LuceneSearchIndexCommand command =
        spy(new LuceneTestSearchIndexCommand(this.mockCache, null));

    final List<Set<LuceneSearchResults>> queryResultsList = new ArrayList<>();
    HashSet<LuceneSearchResults> queryResults = new HashSet<>();
    queryResults.add(createQueryResults("A", "Result1", 1));
    queryResults.add(createQueryResults("B", "Result1", 1));
    queryResults.add(createQueryResults("C", "Result1", 1));
    queryResults.add(createQueryResults("D", "Result1", 1));
    queryResults.add(createQueryResults("E", "Result1", 1));
    queryResults.add(createQueryResults("F", "Result1", 1));
    queryResults.add(createQueryResults("G", "Result1", 1));
    queryResults.add(createQueryResults("H", "Result1", 1));
    queryResults.add(createQueryResults("I", "Result1", 1));
    queryResults.add(createQueryResults("J", "Result1", 1));
    queryResults.add(createQueryResults("K", "Result1", 1));
    queryResults.add(createQueryResults("L", "Result1", 1));
    queryResults.add(createQueryResults("M", "Result1", 1));
    queryResults.add(createQueryResults("N", "Result1", 1));
    queryResults.add(createQueryResults("P", "Result1", 1));
    queryResults.add(createQueryResults("Q", "Result1", 1));
    queryResults.add(createQueryResults("R", "Result1", 1));
    queryResults.add(createQueryResults("S", "Result1", 1));
    queryResults.add(createQueryResults("T", "Result1", 1));
    queryResultsList.add(queryResults);

    doReturn(mockResultCollector).when(command).executeSearch(any(LuceneQueryInfo.class));
    doReturn(queryResultsList).when(mockResultCollector).getResult();

    ResultModel result = command.searchIndex("index", "region", "Result1", "field1", -1, true);
    TabularResultModel data = result.getTableSection("lucene-indexes");
    assertThat(data.getValuesInColumn("key").size()).isEqualTo(queryResults.size());
  }

  @Test
  public void testDestroySingleIndexNoRegionMembers() {
    LuceneDestroyIndexCommand command =
        spy(new LuceneTestDestroyIndexCommand(mockCache, null));
    final List<CliFunctionResult> cliFunctionResults = new ArrayList<>();
    String expectedStatus = CliStrings.format(
        LuceneCliStrings.LUCENE_DESTROY_INDEX__MSG__COULD_NOT_FIND__MEMBERS_GREATER_THAN_VERSION_0,
        new Object[] {Version.GEODE_1_7_0});
    cliFunctionResults.add(new CliFunctionResult("member0", CliFunctionResult.StatusState.OK));
    doReturn(Collections.emptySet()).when(command).getNormalMembersWithSameOrNewerVersion(any());

    ResultModel result = command.destroyIndex("index", "regionPath");
    verifyDestroyIndexCommandResult(result, cliFunctionResults, expectedStatus);
  }

  @Test
  @Parameters({"true", "false"})
  public void testDestroySingleIndexWithRegionMembers(boolean expectedToSucceed) {
    LuceneDestroyIndexCommand command =
        spy(new LuceneTestDestroyIndexCommand(mockCache, null));
    String indexName = "index";
    String regionPath = "regionPath";

    Set<DistributedMember> members = new HashSet<>();
    DistributedMember mockMember = mock(DistributedMember.class);
    when(mockMember.getId()).thenReturn("member0");
    members.add(mockMember);

    final ResultCollector mockResultCollector = mock(ResultCollector.class);
    final List<CliFunctionResult> cliFunctionResults = new ArrayList<>();
    String expectedStatus;
    if (expectedToSucceed) {
      expectedStatus = CliStrings.format(
          LuceneCliStrings.LUCENE_DESTROY_INDEX__MSG__SUCCESSFULLY_DESTROYED_INDEX_0_FROM_REGION_1,
          indexName, regionPath);
      cliFunctionResults
          .add(new CliFunctionResult(mockMember.getId(), CliFunctionResult.StatusState.OK));
    } else {
      Exception e = new IllegalStateException("failed");
      expectedStatus = e.getMessage();
      cliFunctionResults.add(new CliFunctionResult("member0", e, e.getMessage()));
    }

    doReturn(mockResultCollector).when(command).executeFunction(
        any(LuceneDestroyIndexFunction.class), any(LuceneDestroyIndexInfo.class), anySet());
    doReturn(cliFunctionResults).when(mockResultCollector).getResult();

    doReturn(members).when(command).getNormalMembersWithSameOrNewerVersion(any());

    ResultModel result = command.destroyIndex(indexName, regionPath);
    verifyDestroyIndexCommandResult(result, cliFunctionResults, expectedStatus);
  }

  @Test
  public void testDestroyAllIndexesNoRegionMembers() {
    LuceneDestroyIndexCommand commands =
        spy(new LuceneTestDestroyIndexCommand(mockCache, null));
    doReturn(Collections.emptySet()).when(commands).getNormalMembersWithSameOrNewerVersion(any());
    final List<CliFunctionResult> cliFunctionResults = new ArrayList<>();
    String expectedStatus = CliStrings.format(
        LuceneCliStrings.LUCENE_DESTROY_INDEX__MSG__COULD_NOT_FIND__MEMBERS_GREATER_THAN_VERSION_0,
        new Object[] {Version.GEODE_1_7_0});
    cliFunctionResults.add(new CliFunctionResult("member0", CliFunctionResult.StatusState.OK));

    ResultModel result = commands.destroyIndex(null, "regionPath");
    verifyDestroyIndexCommandResult(result, cliFunctionResults, expectedStatus);
  }

  @Test
  @Parameters({"true", "false"})
  public void testDestroyAllIndexesWithRegionMembers(boolean expectedToSucceed) {
    LuceneDestroyIndexCommand commands =
        spy(new LuceneTestDestroyIndexCommand(mockCache, null));
    String indexName = null;
    String regionPath = "regionPath";

    Set<DistributedMember> members = new HashSet<>();
    DistributedMember mockMember = mock(DistributedMember.class);
    when(mockMember.getId()).thenReturn("member0");
    members.add(mockMember);

    final ResultCollector mockResultCollector = mock(ResultCollector.class);
    final List<CliFunctionResult> cliFunctionResults = new ArrayList<>();
    String expectedStatus;
    if (expectedToSucceed) {
      expectedStatus = CliStrings.format(
          LuceneCliStrings.LUCENE_DESTROY_INDEX__MSG__SUCCESSFULLY_DESTROYED_INDEXES_FROM_REGION_0,
          new Object[] {regionPath});
      cliFunctionResults
          .add(new CliFunctionResult(mockMember.getId(), CliFunctionResult.StatusState.OK));
    } else {
      Exception e = new IllegalStateException("failed");
      expectedStatus = e.getMessage();
      cliFunctionResults.add(new CliFunctionResult("member0", e, e.getMessage()));
    }

    doReturn(mockResultCollector).when(commands).executeFunction(
        any(LuceneDestroyIndexFunction.class), any(LuceneDestroyIndexInfo.class), anySet());
    doReturn(cliFunctionResults).when(mockResultCollector).getResult();

    doReturn(members).when(commands).getNormalMembersWithSameOrNewerVersion(any());

    ResultModel result = commands.destroyIndex(indexName, regionPath);
    verifyDestroyIndexCommandResult(result, cliFunctionResults, expectedStatus);
  }

  private void verifyDestroyIndexCommandResult(ResultModel result,
      List<CliFunctionResult> cliFunctionResults, String expectedStatus) {
    assertThat(result.getStatus()).isEqualTo(Status.OK);

    TabularResultModel data = result.getTableSection("lucene-indexes");
    if (data != null) {
      List<String> members = data.getValuesInColumn("Member");
      assertThat(cliFunctionResults.size()).isEqualTo(members.size());
      // Verify each member
      for (int i = 0; i < members.size(); i++) {
        assertThat(members.get(i)).isEqualTo("member" + i);
      }
      // Verify each status
      List<String> status = data.getValuesInColumn("Status");
      for (String statu : status) {
        assertThat(statu).isEqualTo(expectedStatus);
      }
    } else if (result.getInfoSection("info") != null) {
      // Info result. Verify next lines are equal.
      assertThat(result.getInfoSection("info").getContent().get(0)).isEqualTo(expectedStatus);
    } else {
      // Error result. Verify next lines are equal.
      assertThat(result.getInfoSection("error").getContent().get(0)).isEqualTo(expectedStatus);
    }
  }

  private String getPage(final LuceneSearchResults[] expectedResults, int[] indexList) {
    ResultModel resultModel = new ResultModel();
    TabularResultModel data = resultModel.addTable("table");
    for (int i : indexList) {
      data.accumulate("key", expectedResults[i].getKey());
      data.accumulate("value", expectedResults[i].getValue());
      data.accumulate("score", expectedResults[i].getScore() + "");
    }

    return new CommandResult(resultModel).asString();
  }

  private List<Set<LuceneSearchResults>> getSearchResults(LuceneSearchResults... results) {
    final List<Set<LuceneSearchResults>> queryResultsList = new ArrayList<>();
    HashSet<LuceneSearchResults> queryResults = new HashSet<>();
    Collections.addAll(queryResults, results);
    queryResultsList.add(queryResults);
    return queryResultsList;
  }

  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 LuceneIndexDetails createIndexDetails(final String indexName, final String regionPath,
      final String[] searchableFields, final Map<String, Analyzer> fieldAnalyzers,
      LuceneIndexStats indexStats, LuceneIndexStatus status, final String serverName,
      LuceneSerializer serializer) {
    return new LuceneIndexDetails(indexName, regionPath, searchableFields, fieldAnalyzers,
        indexStats, status, serverName, serializer);
  }

  private LuceneIndexDetails createIndexDetails(final String indexName, final String regionPath,
      final String[] searchableFields, final Map<String, Analyzer> fieldAnalyzers,
      LuceneIndexStatus status, final String serverName, LuceneSerializer serializer) {
    return new LuceneIndexDetails(indexName, regionPath, searchableFields, fieldAnalyzers, null,
        status, serverName, serializer);
  }

  private LuceneSearchResults createQueryResults(final String key, final String value,
      final float score) {
    return new LuceneSearchResults(key, value, score);
  }

  private static class LuceneTestListIndexCommand extends LuceneListIndexCommand {
    private final Execution functionExecutor;

    LuceneTestListIndexCommand(final InternalCache cache, final Execution functionExecutor) {
      assert cache != null : "The InternalCache cannot be null!";
      setCache(cache);
      this.functionExecutor = functionExecutor;
    }

    @Override
    public Set<DistributedMember> getAllMembers() {
      return Collections.emptySet();
    }

    @Override
    public Execution getMembersFunctionExecutor(final Set<DistributedMember> members) {
      assertThat(members).isNotNull();
      return this.functionExecutor;
    }
  }

  private static class LuceneTestCreateIndexCommand extends LuceneCreateIndexCommand {
    private final Execution functionExecutor;

    LuceneTestCreateIndexCommand(final InternalCache cache, final Execution functionExecutor) {
      assert cache != null : "The InternalCache cannot be null!";
      setCache(cache);
      this.functionExecutor = functionExecutor;
    }

    @Override
    public Set<DistributedMember> getAllMembers() {
      return Collections.emptySet();
    }

    @Override
    public Execution getMembersFunctionExecutor(final Set<DistributedMember> members) {
      assertThat(members).isNotNull();
      return this.functionExecutor;
    }
  }

  private static class LuceneTestDescribeIndexCommand extends LuceneDescribeIndexCommand {
    private final Execution functionExecutor;

    LuceneTestDescribeIndexCommand(final InternalCache cache, final Execution functionExecutor) {
      assert cache != null : "The InternalCache cannot be null!";
      setCache(cache);
      this.functionExecutor = functionExecutor;
    }

    @Override
    public Set<DistributedMember> getAllMembers() {
      return Collections.emptySet();
    }

    @Override
    public Execution getMembersFunctionExecutor(final Set<DistributedMember> members) {
      assertThat(members).isNotNull();
      return this.functionExecutor;
    }
  }

  private static class LuceneTestSearchIndexCommand extends LuceneSearchIndexCommand {
    private final Execution functionExecutor;

    LuceneTestSearchIndexCommand(final InternalCache cache, final Execution functionExecutor) {
      assert cache != null : "The InternalCache cannot be null!";
      setCache(cache);
      this.functionExecutor = functionExecutor;
    }

    @Override
    public Set<DistributedMember> getAllMembers() {
      return Collections.emptySet();
    }

    @Override
    public Execution getMembersFunctionExecutor(final Set<DistributedMember> members) {
      assertThat(members).isNotNull();
      return this.functionExecutor;
    }
  }

  private static class LuceneTestDestroyIndexCommand extends LuceneDestroyIndexCommand {
    private final Execution functionExecutor;

    LuceneTestDestroyIndexCommand(final InternalCache cache, final Execution functionExecutor) {
      assert cache != null : "The InternalCache cannot be null!";
      setCache(cache);
      this.functionExecutor = functionExecutor;
    }

    @Override
    public Set<DistributedMember> getAllMembers() {
      return Collections.emptySet();
    }

    @Override
    public Execution getMembersFunctionExecutor(final Set<DistributedMember> members) {
      assertThat(members).isNotNull();
      return this.functionExecutor;
    }
  }
}
