/*
 * 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.solr.cloud;

import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.io.FilenameUtils;
import org.apache.lucene.util.TestUtil;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.response.transform.DocTransformer;
import org.apache.solr.response.transform.RawValueTransformerFactory;
import org.apache.solr.response.transform.TransformerFactory;
import org.apache.solr.util.RandomizeSSL;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** @see TestCloudPseudoReturnFields */
@RandomizeSSL(clientAuth=0.0,reason="client auth uses too much RAM")
public class TestRandomFlRTGCloud extends SolrCloudTestCase {
  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
  private static final String DEBUG_LABEL = MethodHandles.lookup().lookupClass().getName();
  private static final String COLLECTION_NAME = DEBUG_LABEL + "_collection";
  
  /** A basic client for operations at the cloud level, default collection will be set */
  private static CloudSolrClient CLOUD_CLIENT;
  /** One client per node */
  private static final List<HttpSolrClient> CLIENTS = Collections.synchronizedList(new ArrayList<>(5));

  /** Always included in fl so we can vet what doc we're looking at */
  private static final FlValidator ID_VALIDATOR = new SimpleFieldValueValidator("id");

  /** Since nested documents are not tested, when _root_ is declared in schema, it is always the same as id */
  private static final FlValidator ROOT_VALIDATOR = new RenameFieldValueValidator("id" , "_root_");
  
  /** 
   * Types of things we will randomly ask for in fl param, and validate in response docs.
   *
   * @see #addRandomFlValidators
   */
  private static final List<FlValidator> FL_VALIDATORS = Collections.unmodifiableList
    (Arrays.<FlValidator>asList(
      new GlobValidator("*"),
      new GlobValidator("*_i"),
      new GlobValidator("*_s"),
      new GlobValidator("a*"),
      new DocIdValidator(),
      new DocIdValidator("my_docid_alias"),
      new ShardValidator(),
      new ShardValidator("my_shard_alias"),
      new ValueAugmenterValidator(42),
      new ValueAugmenterValidator(1976, "val_alias"),
      //
      new RenameFieldValueValidator("id", "my_id_alias"),
      new SimpleFieldValueValidator("aaa_i"),
      new RenameFieldValueValidator("bbb_i", "my_int_field_alias"),
      new SimpleFieldValueValidator("ccc_s"),
      new RenameFieldValueValidator("ddd_s", "my_str_field_alias"),
      //
      // SOLR-9376: RawValueTransformerFactory doesn't work in cloud mode 
      //
      // new RawFieldValueValidator("json", "eee_s", "my_json_field_alias"),
      // new RawFieldValueValidator("json", "fff_s"),
      // new RawFieldValueValidator("xml", "ggg_s", "my_xml_field_alias"),
      // new RawFieldValueValidator("xml", "hhh_s"),
      //
      new NotIncludedValidator("bogus_unused_field_ss"),
      new NotIncludedValidator("bogus_alias","bogus_alias:other_bogus_field_i"),
      new NotIncludedValidator("bogus_raw_alias","bogus_raw_alias:[xml f=bogus_raw_field_ss]"),
      //
      new FunctionValidator("aaa_i"), // fq field
      new FunctionValidator("aaa_i", "func_aaa_alias"),
      new GeoTransformerValidator("geo_1_srpt"),
      new GeoTransformerValidator("geo_2_srpt","my_geo_alias"),
      new ExplainValidator(),
      new ExplainValidator("explain_alias"),
      new SubQueryValidator(),
      new NotIncludedValidator("score"),
      new NotIncludedValidator("score","score_alias:score")));
  
  @BeforeClass
  public static void createMiniSolrCloudCluster() throws Exception {

    // 50% runs use single node/shard a FL_VALIDATORS with all validators known to work on single node
    // 50% runs use multi node/shard with FL_VALIDATORS only containing stuff that works in cloud
    final boolean singleCoreMode = random().nextBoolean();

    // (asuming multi core multi replicas shouldn't matter (assuming multi node) ...
    final int repFactor = singleCoreMode ? 1 : (usually() ? 1 : 2);
    // ... but we definitely want to ensure forwarded requests to other shards work ...
    final int numShards = singleCoreMode ? 1 : 2;
    // ... including some forwarded requests from nodes not hosting a shard
    final int numNodes = 1 + (singleCoreMode ? 0 : (numShards * repFactor));
    
    final String configName = DEBUG_LABEL + "_config-set";
    final Path configDir = Paths.get(TEST_HOME(), "collection1", "conf");
    
    configureCluster(numNodes).addConfig(configName, configDir).configure();

    CLOUD_CLIENT = cluster.getSolrClient();
    CLOUD_CLIENT.setDefaultCollection(COLLECTION_NAME);

    CollectionAdminRequest.createCollection(COLLECTION_NAME, configName, numShards, repFactor)
        .withProperty("config", "solrconfig-tlog.xml")
        .withProperty("schema", "schema-psuedo-fields.xml")
        .process(CLOUD_CLIENT);

    cluster.waitForActiveCollection(COLLECTION_NAME, numShards, repFactor * numShards); 

    for (JettySolrRunner jetty : cluster.getJettySolrRunners()) {
      CLIENTS.add(getHttpSolrClient(jetty.getBaseUrl() + "/" + COLLECTION_NAME + "/"));
    }
  }

  @AfterClass
  private static void afterClass() throws Exception {
    if (null != CLOUD_CLIENT) {
      CLOUD_CLIENT.close();
      CLOUD_CLIENT = null;
    }
    for (HttpSolrClient client : CLIENTS) {
      client.close();
    }
    CLIENTS.clear();
  }

  /** 
   * Tests that all TransformerFactories that are implicitly provided by Solr are tested in this class
   *
   * @see FlValidator#getDefaultTransformerFactoryName
   * @see #FL_VALIDATORS
   * @see TransformerFactory#defaultFactories
   */
  public void testCoverage() throws Exception {
    final Set<String> implicit = new LinkedHashSet<>();
    for (String t :  TransformerFactory.defaultFactories.keySet()) {
      implicit.add(t);
    }
    
    final Set<String> covered = new LinkedHashSet<>();
    for (FlValidator v : FL_VALIDATORS) {
      String t = v.getDefaultTransformerFactoryName();
      if (null != t) {
        covered.add(t);
      }
    }

    // items should only be added to this list if it's known that they do not work with RTG
    // and a specific Jira for fixing this is listed as a comment
    final List<String> knownBugs = Arrays.asList
      ( "xml","json", // SOLR-9376
        "child" // way to complicatd to vet with this test, see SOLR-9379 instead
      );

    for (String buggy : knownBugs) {
      assertFalse(buggy + " is listed as a being a known bug, " +
                  "but it exists in the set of 'covered' TransformerFactories",
                  covered.contains(buggy));
      assertTrue(buggy + " is listed as a known bug, " +
                 "but it does not even exist in the set of 'implicit' TransformerFactories",
                  implicit.remove(buggy));
    }
    
    implicit.removeAll(covered);
    assertEquals("Some implicit TransformerFactories are not yet tested by this class: " + implicit,
                 0, implicit.size());
  }


  public void testRandomizedUpdatesAndRTGs() throws Exception {

    final int maxNumDocs = atLeast(100);
    final int numSeedDocs = random().nextInt(maxNumDocs / 10); // at most ~10% of the max possible docs
    final int numIters = atLeast(maxNumDocs * 10);
    final SolrInputDocument[] knownDocs = new SolrInputDocument[maxNumDocs];

    log.info("Starting {} iters by seeding {} of {} max docs",
             numIters, numSeedDocs, maxNumDocs);

    int itersSinceLastCommit = 0;
    for (int i = 0; i < numIters; i++) {
      itersSinceLastCommit = maybeCommit(random(), itersSinceLastCommit, numIters);

      if (i < numSeedDocs) {
        // first N iters all we worry about is seeding
        knownDocs[i] = addRandomDocument(i);
      } else {
        assertOneIter(knownDocs);
      }
    }
  }

  /** 
   * Randomly chooses to do a commit, where the probability of doing so increases the longer it's been since 
   * a commit was done.
   *
   * @returns <code>0</code> if a commit was done, else <code>itersSinceLastCommit + 1</code>
   */
  private static int maybeCommit(final Random rand, final int itersSinceLastCommit, final int numIters) throws IOException, SolrServerException {
    final float threshold = itersSinceLastCommit / numIters;
    if (rand.nextFloat() < threshold) {
      log.info("COMMIT");
      assertEquals(0, getRandClient(rand).commit().getStatus());
      return 0;
    }
    return itersSinceLastCommit + 1;
  }
  
  private void assertOneIter(final SolrInputDocument[] knownDocs) throws IOException, SolrServerException {
    // we want to occasionally test more then one doc per RTG
    final int numDocsThisIter = TestUtil.nextInt(random(), 1, atLeast(2));
    int numDocsThisIterThatExist = 0;
    
    // pick some random docIds for this iteration and ...
    final int[] docIds = new int[numDocsThisIter];
    for (int i = 0; i < numDocsThisIter; i++) {
      docIds[i] = random().nextInt(knownDocs.length);
      if (null != knownDocs[docIds[i]]) {
        // ...check how many already exist
        numDocsThisIterThatExist++;
      }
    }

    // we want our RTG requests to occasionally include missing/deleted docs,
    // but that's not the primary focus of the test, so weight the odds accordingly
    if (random().nextInt(numDocsThisIter + 2) <= numDocsThisIterThatExist) {

      if (0 < TestUtil.nextInt(random(), 0, 13)) {
        log.info("RTG: numDocsThisIter={} numDocsThisIterThatExist={}, docIds={}",
                 numDocsThisIter, numDocsThisIterThatExist, docIds);
        assertRTG(knownDocs, docIds);
      } else {
        // sporadically delete some docs instead of doing an RTG
        log.info("DEL: numDocsThisIter={} numDocsThisIterThatExist={}, docIds={}",
                 numDocsThisIter, numDocsThisIterThatExist, docIds);
        assertDelete(knownDocs, docIds);
      }
    } else {
      log.info("UPD: numDocsThisIter={} numDocsThisIterThatExist={}, docIds={}",
               numDocsThisIter, numDocsThisIterThatExist, docIds);
      assertUpdate(knownDocs, docIds);
    }
  }

  /**
   * Does some random indexing of the specified docIds and adds them to knownDocs
   */
  private void assertUpdate(final SolrInputDocument[] knownDocs, final int[] docIds) throws IOException, SolrServerException {
    
    for (final int docId : docIds) {
      // TODO: this method should also do some atomic update operations (ie: "inc" and "set")
      // (but make sure to eval the updates locally as well before modifying knownDocs)
      knownDocs[docId] = addRandomDocument(docId);
    }
  }
  
  /**
   * Deletes the docIds specified and asserts the results are valid, updateing knownDocs accordingly
   */
  private void assertDelete(final SolrInputDocument[] knownDocs, final int[] docIds) throws IOException, SolrServerException {
    List<String> ids = new ArrayList<>(docIds.length);
    for (final int docId : docIds) {
      ids.add("" + docId);
      knownDocs[docId] = null;
    }
    assertEquals("Failed delete: " + docIds, 0, getRandClient(random()).deleteById(ids).getStatus());
  }
  
  /**
   * Adds one randomly generated document with the specified docId, asserting success, and returns 
   * the document added
   */
  private SolrInputDocument addRandomDocument(final int docId) throws IOException, SolrServerException {
    final SolrClient client = getRandClient(random());

    final SolrInputDocument doc = sdoc("id", "" + docId,
                                       "aaa_i", random().nextInt(),
                                       "bbb_i", random().nextInt(),
                                       //
                                       "ccc_s", TestUtil.randomSimpleString(random()),
                                       "ddd_s", TestUtil.randomSimpleString(random()),
                                       "eee_s", TestUtil.randomSimpleString(random()),
                                       "fff_s", TestUtil.randomSimpleString(random()),
                                       "ggg_s", TestUtil.randomSimpleString(random()),
                                       "hhh_s", TestUtil.randomSimpleString(random()),
                                       //
                                       "geo_1_srpt", GeoTransformerValidator.getValueForIndexing(random()),
                                       "geo_2_srpt", GeoTransformerValidator.getValueForIndexing(random()),
                                       // for testing subqueries
                                       "next_2_ids_ss", String.valueOf(docId + 1),
                                       "next_2_ids_ss", String.valueOf(docId + 2),
                                       // for testing prefix globbing
                                       "axx_i", random().nextInt(),
                                       "ayy_i", random().nextInt(),
                                       "azz_s", TestUtil.randomSimpleString(random()));
    
    log.info("ADD: {} = {}", docId, doc);
    assertEquals(0, client.add(doc).getStatus());
    return doc;
  }

  
  /**
   * Does one or more RTG request for the specified docIds with a randomized fl &amp; fq params, asserting
   * that the returned document (if any) makes sense given the expected SolrInputDocuments
   */
  private void assertRTG(final SolrInputDocument[] knownDocs, final int[] docIds) throws IOException, SolrServerException {
    final SolrClient client = getRandClient(random());
    // NOTE: not using SolrClient.getById or getByIds because we want to force choice of "id" vs "ids" params
    final ModifiableSolrParams params = params("qt","/get");
    
    // random fq -- nothing fancy, secondary concern for our test
    final Integer FQ_MAX = usually() ? null : random().nextInt();
    if (null != FQ_MAX) {
      params.add("fq", "aaa_i:[* TO " + FQ_MAX + "]");
    }
    
    final Set<FlValidator> validators = new LinkedHashSet<>();
    validators.add(ID_VALIDATOR); // always include id so we can be confident which doc we're looking at
    validators.add(ROOT_VALIDATOR); // always added in a nested schema, with the same value as id
    addRandomFlValidators(random(), validators);
    FlValidator.addParams(validators, params);

    final List<String> idsToRequest = new ArrayList<>(docIds.length);
    final List<SolrInputDocument> docsToExpect = new ArrayList<>(docIds.length);
    for (int docId : docIds) {
      // every docId will be included in the request
      idsToRequest.add("" + docId);
      
      // only docs that should actually exist and match our (optional) filter will be expected in response
      if (null != knownDocs[docId]) {
        Integer filterVal = (Integer) knownDocs[docId].getFieldValue("aaa_i");
        if (null == FQ_MAX || ((null != filterVal) && filterVal.intValue() <= FQ_MAX.intValue())) {
          docsToExpect.add(knownDocs[docId]);
        }
      }
    }

    // even w/only 1 docId requested, the response format can vary depending on how we request it
    final boolean askForList = random().nextBoolean() || (1 != idsToRequest.size());
    if (askForList) {
      if (1 == idsToRequest.size()) {
        // have to be careful not to try to use "multi" 'id' params with only 1 docId
        // with a single docId, the only way to ask for a list is with the "ids" param
        params.add("ids", idsToRequest.get(0));
      } else {
        if (random().nextBoolean()) {
          // each id in its own param
          for (String id : idsToRequest) {
            params.add("id",id);
          }
        } else {
          // add one or more comma separated ids params
          params.add(buildCommaSepParams(random(), "ids", idsToRequest));
        }
      }
    } else {
      assert 1 == idsToRequest.size();
      params.add("id",idsToRequest.get(0));
    }
    
    final QueryResponse rsp = client.query(params);
    assertNotNull(params.toString(), rsp);

    final SolrDocumentList docs = getDocsFromRTGResponse(askForList, rsp);
    assertNotNull(params + " => " + rsp, docs);
    
    assertEquals("num docs mismatch: " + params + " => " + docsToExpect + " vs " + docs,
                 docsToExpect.size(), docs.size());
    
    // NOTE: RTG makes no garuntees about the order docs will be returned in when multi requested
    for (SolrDocument actual : docs) {
      try {
        int actualId = assertParseInt("id", actual.getFirstValue("id"));
        final SolrInputDocument expected = knownDocs[actualId];
        assertNotNull("expected null doc but RTG returned: " + actual, expected);
        
        Set<String> expectedFieldNames = new TreeSet<>();
        for (FlValidator v : validators) {
          expectedFieldNames.addAll(v.assertRTGResults(validators, expected, actual));
        }
        // ensure only expected field names are in the actual document
        Set<String> actualFieldNames = new TreeSet<>(actual.getFieldNames());
        assertEquals("Actual field names returned differs from expected", expectedFieldNames, actualFieldNames);
      } catch (AssertionError ae) {
        throw new AssertionError(params + " => " + actual + ": " + ae.getMessage(), ae);
      }
    }
  }

  /** 
   * trivial helper method to deal with diff response structure between using a single 'id' param vs
   * 2 or more 'id' params (or 1 or more 'ids' params).
   *
   * @return List from response, or a synthetic one created from single response doc if 
   * <code>expectList</code> was false; May be empty; May be null if response included null list.
   */
  private static SolrDocumentList getDocsFromRTGResponse(final boolean expectList, final QueryResponse rsp) {
    if (expectList) {
      return rsp.getResults();
    }
    
    // else: expect single doc, make our own list...
    
    final SolrDocumentList result = new SolrDocumentList();
    NamedList<Object> raw = rsp.getResponse();
    Object doc = raw.get("doc");
    if (null != doc) {
      result.add((SolrDocument) doc);
      result.setNumFound(1);
    }
    return result;
  }
    
  /** 
   * returns a random SolrClient -- either a CloudSolrClient, or an HttpSolrClient pointed 
   * at a node in our cluster 
   */
  public static SolrClient getRandClient(Random rand) {
    int numClients = CLIENTS.size();
    int idx = TestUtil.nextInt(rand, 0, numClients);
    return (idx == numClients) ? CLOUD_CLIENT : CLIENTS.get(idx);
  }

  public static void waitForRecoveriesToFinish(CloudSolrClient client) throws Exception {
    assert null != client.getDefaultCollection();
    AbstractDistribZkTestBase.waitForRecoveriesToFinish(client.getDefaultCollection(),
                                                        client.getZkStateReader(),
                                                        true, true, 330);
  }

  /** 
   * Abstraction for diff types of things that can be added to an 'fl' param that can validate
   * the results are correct compared to an expected SolrInputDocument
   */
  private interface FlValidator {
    
    /** 
     * Given a list of FlValidators, adds one or more fl params that corrispond to the entire set, 
     * as well as any other special case top level params required by the validators.
     */
    public static void addParams(final Collection<FlValidator> validators, final ModifiableSolrParams params) {
      final List<String> fls = new ArrayList<>(validators.size());
      for (FlValidator v : validators) {
        params.add(v.getExtraRequestParams());
        fls.add(v.getFlParam());
      }
      params.add(buildCommaSepParams(random(), "fl", fls));
    }

    /**
     * Indicates if this validator is for a transformer that returns true from 
     * {@link DocTransformer#needsSolrIndexSearcher}.  Other validators for transformers that 
     * do <em>not</em> require a re-opened searcher (but may have slightly diff behavior depending 
     * on wether a doc comesfrom the index or from the update log) may use this information to 
     * decide wether they wish to enforce stricter assertions on the resulting document.
     *
     * The default implementation always returns <code>false</code>
     *
     * @see DocIdValidator
     */
    public default boolean requiresRealtimeSearcherReOpen() {
      return false;
    }

    /**
     * the name of a transformer listed in {@link TransformerFactory#defaultFactories} that this validator
     * corrisponds to, or null if not applicable.  Used for testing coverage of 
     * Solr's implicitly supported transformers.
     *
     * Default behavior is to return null
     * @see #testCoverage
     */
    public default String getDefaultTransformerFactoryName() { return null; }
    
    /**
     * Any special case params that must be added to the request for this validator
     */
    public default SolrParams getExtraRequestParams() { return params(); }
    
    /** 
     * Must return a non null String that can be used in an fl param -- either by itself, 
     * or with other items separated by commas
     */
    public String getFlParam();

    /** 
     * Given the expected document and the actual document returned from an RTG, this method
     * should assert that relative to what {@link #getFlParam} returns, the actual document contained
     * what it should relative to the expected document.
     *
     * @param validators all validators in use for this request, including the current one
     * @param expected a document containing the expected fields &amp; values that should be in the index
     * @param actual A document that was returned by an RTG request
     * @return A set of "field names" in the actual document that this validator expected.
     */
    public Collection<String> assertRTGResults(final Collection<FlValidator> validators,
                                               final SolrInputDocument expected,
                                               final SolrDocument actual);
  }
  
  /** 
   * Some validators behave in a way that "suppresses" real fields even when they would otherwise match a glob
   * @see GlobValidator
   */
  private interface SuppressRealFields {
    public Set<String> getSuppressedFields();
  }

  private abstract static class FieldValueValidator implements FlValidator {
    protected final String expectedFieldName;
    protected final String actualFieldName;
    public FieldValueValidator(final String expectedFieldName, final String actualFieldName) {
      this.expectedFieldName = expectedFieldName;
      this.actualFieldName = actualFieldName;
    }
    public abstract String getFlParam();
    public Collection<String> assertRTGResults(final Collection<FlValidator> validators,
                                               final SolrInputDocument expected,
                                               final SolrDocument actual) {
      assertEquals(expectedFieldName + " vs " + actualFieldName,
                   expected.getFieldValue(expectedFieldName), actual.getFirstValue(actualFieldName));
      return Collections.<String>singleton(actualFieldName);
    }
  }
  
  private static class SimpleFieldValueValidator extends FieldValueValidator {
    public SimpleFieldValueValidator(final String fieldName) {
      super(fieldName, fieldName);
    }
    public String getFlParam() { return expectedFieldName; }
  }
  
  private static class RenameFieldValueValidator extends FieldValueValidator implements SuppressRealFields {
    public RenameFieldValueValidator(final String origFieldName, final String alias) {
      super(origFieldName, alias);
    }
    public String getFlParam() { return actualFieldName + ":" + expectedFieldName; }
    public Set<String> getSuppressedFields() { return Collections.singleton(expectedFieldName); }
  }

  /**
   * Validator for {@link RawValueTransformerFactory}
   *
   * This validator is fairly weak, because it doesn't do anything to verify the conditional logic
   * in RawValueTransformerFactory realted to the output format -- but that's out of the scope of 
   * this randomized testing.  
   * 
   * What we're primarily concerned with is that the transformer does it's job and puts the string 
   * in the response, regardless of cloud/RTG/uncommited state of the document.
   */
  private static class RawFieldValueValidator extends RenameFieldValueValidator {
    final String type;
    final String alias;
    public RawFieldValueValidator(final String type, final String fieldName, final String alias) {
      // transformer is weird, default result key doesn't care what params are used...
      super(fieldName, null == alias ? "["+type+"]" : alias);
      this.type = type;
      this.alias = alias;
    }
    public RawFieldValueValidator(final String type, final String fieldName) {
      this(type, fieldName, null);
    }
    public String getFlParam() {
      return (null == alias ? "" : (alias + ":")) + "[" + type + " f=" + expectedFieldName + "]";
    }
    public String getDefaultTransformerFactoryName() {
      return type;
    }
  }
 

  /** 
   * enforces that a valid <code>[docid]</code> is present in the response, possibly using a 
   * resultKey alias.  By default the only validation of docId values is that they are an integer 
   * greater than or equal to <code>-1</code> -- but if any other validator in use returns true 
   * from {@link #requiresRealtimeSearcherReOpen} then the constraint is tightened and values must 
   * be greater than or equal to <code>0</code> 
   */
  private static class DocIdValidator implements FlValidator {
    private static final String NAME = "docid";
    private static final String USAGE = "["+NAME+"]";
    private final String resultKey;
    public DocIdValidator(final String resultKey) {
      this.resultKey = resultKey;
    }
    public DocIdValidator() {
      this(USAGE);
    }
    public String getDefaultTransformerFactoryName() { return NAME; }
    public String getFlParam() { return USAGE.equals(resultKey) ? resultKey : resultKey+":"+USAGE; }
    public Collection<String> assertRTGResults(final Collection<FlValidator> validators,
                                               final SolrInputDocument expected,
                                               final SolrDocument actual) {
      final Object value =  actual.getFirstValue(resultKey);
      assertNotNull(getFlParam() + " => no value in actual doc", value);
      assertTrue(USAGE + " must be an Integer: " + value, value instanceof Integer);

      int minValidDocId = -1; // if it comes from update log
      for (FlValidator other : validators) {
        if (other.requiresRealtimeSearcherReOpen()) {
          minValidDocId = 0;
          break;
        }
      }
      assertTrue(USAGE + " must be >= " + minValidDocId + ": " + value,
                 minValidDocId <= ((Integer)value).intValue());
      return Collections.<String>singleton(resultKey);
    }
  }

  /** Trivial validator of ShardAugmenterFactory */
  private static class ShardValidator implements FlValidator {
    private static final String NAME = "shard";
    private static final String USAGE = "["+NAME+"]";
    private final String resultKey;
    public ShardValidator(final String resultKey) {
      this.resultKey = resultKey;
    }
    public ShardValidator() {
      this(USAGE);
    }
    public String getDefaultTransformerFactoryName() { return NAME; }
    public String getFlParam() { return USAGE.equals(resultKey) ? resultKey : resultKey+":"+USAGE; }
    public Collection<String> assertRTGResults(final Collection<FlValidator> validators,
                                               final SolrInputDocument expected,
                                               final SolrDocument actual) {
      final Object value =  actual.getFirstValue(resultKey);
      assertNotNull(getFlParam() + " => no value in actual doc", value);
      assertTrue(USAGE + " must be an String: " + value, value instanceof String);

      // trivial sanity check
      assertFalse(USAGE + " => blank string", value.toString().trim().isEmpty());
      return Collections.<String>singleton(resultKey);
    }
  }

  /** Trivial validator of ValueAugmenter */
  private static class ValueAugmenterValidator implements FlValidator {
    private static final String NAME = "value";
    private static String trans(final int value) { return "[" + NAME + " v=" + value + " t=int]"; }
    
    private final String resultKey;
    private final String fl;
    private final Integer expectedVal;
    private ValueAugmenterValidator(final String fl, final int expectedVal, final String resultKey) {
      this.resultKey = resultKey;
      this.expectedVal = expectedVal;
      this.fl = fl;
    }
    public ValueAugmenterValidator(final int expectedVal, final String resultKey) {
      this(resultKey + ":" +trans(expectedVal), expectedVal, resultKey);
    }
    public ValueAugmenterValidator(final int expectedVal) {
      // value transformer is weird, default result key doesn't care what params are used...
      this(trans(expectedVal), expectedVal, "["+NAME+"]");
    }
    public String getDefaultTransformerFactoryName() { return NAME; }
    public String getFlParam() { return fl; }
    public Collection<String> assertRTGResults(final Collection<FlValidator> validators,
                                               final SolrInputDocument expected,
                                               final SolrDocument actual) {
      final Object actualVal =  actual.getFirstValue(resultKey);
      assertNotNull(getFlParam() + " => no value in actual doc", actualVal);
      assertEquals(getFlParam(), expectedVal, actualVal);
      return Collections.<String>singleton(resultKey);
    }
  }

  
  /** Trivial validator of a ValueSourceAugmenter */
  private static class FunctionValidator implements FlValidator {
    private static String func(String fieldName) {
      return "add(1.3,sub("+fieldName+","+fieldName+"))";
    }
    protected final String fl;
    protected final String resultKey;
    protected final String fieldName;
    public FunctionValidator(final String fieldName) {
      this(func(fieldName), fieldName, func(fieldName));
    }
    public FunctionValidator(final String fieldName, final String resultKey) {
      this(resultKey + ":" + func(fieldName), fieldName, resultKey);
    }
    private FunctionValidator(final String fl, final String fieldName, final String resultKey) {
      this.fl = fl;
      this.resultKey = resultKey;
      this.fieldName = fieldName;
    }
    /** always returns true */
    public boolean requiresRealtimeSearcherReOpen() { return true; }
    public String getFlParam() { return fl; }
    public Collection<String> assertRTGResults(final Collection<FlValidator> validators,
                                               final SolrInputDocument expected,
                                               final SolrDocument actual) {
      final Object origVal = expected.getFieldValue(fieldName);
      assertTrue("this validator only works on numeric fields: " + origVal, origVal instanceof Number);
      
      assertEquals(fl, 1.3F, actual.getFirstValue(resultKey));
      return Collections.<String>singleton(resultKey);
    }
  }

  
  /** 
   * Trivial validator of a SubQueryAugmenter.  
   *
   * This validator ignores 90% of the features/complexity
   * of SubQueryAugmenter, and instead just focuses on the basics of:
   * <ul>
   *  <li>do a subquery for docs where SUBQ_FIELD contains the id of the top level doc</li>
   *  <li>verify that any subquery match is expected based on indexing pattern</li>
   * </ul>
   */
  private static class SubQueryValidator implements FlValidator {

    // HACK to work around SOLR-9396...
    // 
    // we're using "id" (and only "id") in the subquery.q as a workarround limitation in
    // "$rows.foo" parsing -- it only works reliably if "foo" is in fl, so we only use "$rows.id",
    // which we know is in every request (and is a valid integer)
    
    public final static String NAME = "subquery";
    public final static String SUBQ_KEY = "subq";
    public final static String SUBQ_FIELD = "next_2_ids_i";
    public String getFlParam() { return SUBQ_KEY+":["+NAME+"]"; }
    public Collection<String> assertRTGResults(final Collection<FlValidator> validators,
                                               final SolrInputDocument expected,
                                               final SolrDocument actual) {
      final int compVal = assertParseInt("expected id", expected.getFieldValue("id"));
      
      final Object actualVal = actual.getFieldValue(SUBQ_KEY);
      assertTrue("Expected a doclist: " + actualVal,
                 actualVal instanceof SolrDocumentList);
      assertTrue("should be at most 2 docs in doc list: " + actualVal,
                 ((SolrDocumentList) actualVal).getNumFound() <= 2);
      
      for (SolrDocument subDoc : (SolrDocumentList) actualVal) {
        final int subDocIdVal = assertParseInt("subquery id", subDoc.getFirstValue("id"));
        assertTrue("subDocId="+subDocIdVal+" not in valid range for id="+compVal+" (expected "
                   + (compVal-1) + " or " + (compVal-2) + ")",
                   ((subDocIdVal < compVal) && ((compVal-2) <= subDocIdVal)));
        
      }
    
      return Collections.<String>singleton(SUBQ_KEY);
    }
    public String getDefaultTransformerFactoryName() { return NAME; }
    public SolrParams getExtraRequestParams() {
      return params(SubQueryValidator.SUBQ_KEY + ".q",
                    "{!field f=" + SubQueryValidator.SUBQ_FIELD + " v=$row.id}");
    }
  }
  
  /** Trivial validator of a GeoTransformer */
  private static class GeoTransformerValidator implements FlValidator, SuppressRealFields{
    private static final String NAME = "geo";
    /** 
     * we're not worried about testing the actual geo parsing/formatting of values,
     * just that the transformer gets called with the expected field value.
     * so have a small set of fixed input values we use when indexing docs,
     * and the expected output for each
     */
    private static final Map<String,String> VALUES = new HashMap<>();
    /** 
     * The set of legal field values this validator is willing to test as a list so we can
     * reliably index into it with random ints
     */
    private static final List<String> ALLOWED_FIELD_VALUES;
    static {
      for (int i = -42; i < 66; i+=13) {
        VALUES.put("POINT( 42 "+i+" )", "{\"type\":\"Point\",\"coordinates\":[42,"+i+"]}");
      }
      ALLOWED_FIELD_VALUES = Collections.unmodifiableList(new ArrayList<>(VALUES.keySet()));
    }
    /** 
     * returns a random field value usable when indexing a document that this validator will
     * be able to handle.
     */
    public static String getValueForIndexing(final Random rand) {
      return ALLOWED_FIELD_VALUES.get(rand.nextInt(ALLOWED_FIELD_VALUES.size()));
    }
    private static String trans(String fieldName) {
      return "["+NAME+" f="+fieldName+"]";
    }
    protected final String fl;
    protected final String resultKey;
    protected final String fieldName;
    public GeoTransformerValidator(final String fieldName) {
      // geo transformer is weird, default result key doesn't care what params are used...
      this(trans(fieldName), fieldName, "["+NAME+"]");
    }
    public GeoTransformerValidator(final String fieldName, final String resultKey) {
      this(resultKey + ":" + trans(fieldName), fieldName, resultKey);
    }
    private GeoTransformerValidator(final String fl, final String fieldName, final String resultKey) {
      this.fl = fl;
      this.resultKey = resultKey;
      this.fieldName = fieldName;
    }
    public String getDefaultTransformerFactoryName() { return NAME; }
    public String getFlParam() { return fl; }
    public Collection<String> assertRTGResults(final Collection<FlValidator> validators,
                                               final SolrInputDocument expected,
                                               final SolrDocument actual) {
      final Object origVal = expected.getFieldValue(fieldName);
      assertTrue(fl + ": orig field value is not supported: " + origVal, VALUES.containsKey(origVal));
      
      assertEquals(fl, VALUES.get(origVal), actual.getFirstValue(resultKey));
      return Collections.<String>singleton(resultKey);
    }
    public Set<String> getSuppressedFields() { return Collections.singleton(fieldName); }
  }

  /** 
   * Glob based validator.
   * This class checks that every field in the expected doc exists in the actual doc with the expected 
   * value -- with special exceptions for fields that are "suppressed" (usually via an alias)
   *
   * By design, fields that are aliased are "moved" unless the original field name was explicitly included 
   * in the fl, globs don't count.
   *
   * @see RenameFieldValueValidator
   */
  private static class GlobValidator implements FlValidator {
    private final String glob;
    public GlobValidator(final String glob) {
      this.glob = glob;
    }
    private final Set<String> matchingFieldsCache = new LinkedHashSet<>();
    
    public String getFlParam() { return glob; }
    
    private boolean matchesGlob(final String fieldName) {
      if ( FilenameUtils.wildcardMatch(fieldName, glob) ) {
        matchingFieldsCache.add(fieldName); // Don't calculate it again
        return true;
      }
      return false;
    }
                                
    public Collection<String> assertRTGResults(final Collection<FlValidator> validators,
                                               final SolrInputDocument expected,
                                               final SolrDocument actual) {

      final Set<String> renamed = new LinkedHashSet<>(validators.size());
      for (FlValidator v : validators) {
        if (v instanceof SuppressRealFields) {
          renamed.addAll(((SuppressRealFields)v).getSuppressedFields());
        }
      }
      
      // every real field name matching the glob that is not renamed should be in the results
      Set<String> result = new LinkedHashSet<>(expected.getFieldNames().size());
      for (String f : expected.getFieldNames()) {
        if ( matchesGlob(f) && (! renamed.contains(f) ) ) {
          result.add(f);
          assertEquals(glob + " => " + f, expected.getFieldValue(f), actual.getFirstValue(f));
        }
      }
      return result;
    }
  }
  
  /** 
   * for things like "score" and "[explain]" where we explicitly expect what we ask for in the fl
   * to <b>not</b> be returned when using RTG.
   */
  private static class NotIncludedValidator implements FlValidator {
    private final String fieldName;
    private final String fl;
    public NotIncludedValidator(final String fl) {
      this(fl, fl);
    }
    public NotIncludedValidator(final String fieldName, final String fl) {
      this.fieldName = fieldName;
      this.fl = fl;
    }
    public String getFlParam() { return fl; }
    public Collection<String> assertRTGResults(final Collection<FlValidator> validators,
                                               final SolrInputDocument expected,
                                               final SolrDocument actual) {
      assertEquals(fl, null, actual.getFirstValue(fieldName));
      return Collections.emptySet();
    }
  }

  /** explain should always be ignored when using RTG */
  private static class ExplainValidator extends NotIncludedValidator {
    private final static String NAME = "explain";
    private final static String USAGE = "[" + NAME + "]";
    public ExplainValidator() {
      super(USAGE);
    }
    public ExplainValidator(final String resultKey) {
      super(USAGE, resultKey + ":" + USAGE);
    }
    public String getDefaultTransformerFactoryName() { return NAME; }
  }

  /** helper method for adding a random number (may be 0) of items from {@link #FL_VALIDATORS} */
  private static void addRandomFlValidators(final Random r, final Set<FlValidator> validators) {
    List<FlValidator> copyToShuffle = new ArrayList<>(FL_VALIDATORS);
    Collections.shuffle(copyToShuffle, r);
    final int numToReturn = r.nextInt(copyToShuffle.size());
    validators.addAll(copyToShuffle.subList(0, numToReturn + 1));
  }

  /**
   * Given an ordered list of values to include in a (key) param, randomly groups them (ie: comma separated) 
   * into actual param key=values which are returned as a new SolrParams instance
   */
  private static SolrParams buildCommaSepParams(final Random rand, final String key, Collection<String> values) {
    ModifiableSolrParams result = new ModifiableSolrParams();
    List<String> copy = new ArrayList<>(values);
    while (! copy.isEmpty()) {
      List<String> slice = copy.subList(0, random().nextInt(1 + copy.size()));
      result.add(key,String.join(",",slice));
      slice.clear();
    }
    return result;
  }

  /** helper method for asserting an object is a non-null String can be parsed as an int */
  public static int assertParseInt(String msg, Object orig) {
    assertNotNull(msg + ": is null", orig);
    assertTrue(msg + ": is not a string: " + orig, orig instanceof String);
    try {
      return Integer.parseInt(orig.toString());
    } catch (NumberFormatException nfe) {
      throw new AssertionError(msg + ": can't be parsed as a number: " + orig, nfe);
    }
  }
}
