You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sa...@apache.org on 2017/07/11 00:00:14 UTC

[1/6] lucene-solr:master: SOLR-10796: TestPointFields: increase randomized testing of non-trivial values

Repository: lucene-solr
Updated Branches:
  refs/heads/branch_7_0 fd0e520d4 -> 0511aeb51
  refs/heads/branch_7x 95d4a7f3a -> 83400bd81
  refs/heads/master 20153595a -> 5bb09e085


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb09e08/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/TestPointFields.java b/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
index a1d2260..3dac18c 100644
--- a/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
+++ b/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
@@ -17,17 +17,24 @@
 package org.apache.solr.schema;
 
 import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
 import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
@@ -69,13 +76,13 @@ import org.junit.Test;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
-/**
- * Tests for PointField functionality
- *
- *
- */
+/** Tests for PointField functionality */
 public class TestPointFields extends SolrTestCaseJ4 {
-  
+
+  // long overflow can occur in some date calculations if gaps are too large, so we limit to a million years BC & AD.
+  private static final long MIN_DATE_EPOCH_MILLIS = LocalDateTime.parse("-1000000-01-01T00:00:00").toInstant(ZoneOffset.ofHours(0)).toEpochMilli();
+  private static final long MAX_DATE_EPOCH_MILLIS = LocalDateTime.parse("+1000000-01-01T00:00:00").toInstant(ZoneOffset.ofHours(0)).toEpochMilli();
+
   private static final String[] FIELD_SUFFIXES = new String[] {
       "", "_dv", "_mv", "_mv_dv", "_ni", "_ni_dv", "_ni_dv_ns", "_ni_dv_ns_mv", 
       "_ni_mv", "_ni_mv_dv", "_ni_ns", "_ni_ns_mv", "_dv_ns", "_ni_ns_dv", "_dv_ns_mv",
@@ -115,9 +122,11 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testIntPointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_i", "int", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99"});
-    testPointFieldReturn("number_p_i_dv_ns", "int", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99"});
-    testPointFieldReturn("number_p_i_ni", "int", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99"});
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] ints = toStringArray(getRandomInts(numValues, false));
+    testPointFieldReturn("number_p_i", "int", ints);
+    testPointFieldReturn("number_p_i_dv_ns", "int", ints);
+    testPointFieldReturn("number_p_i_ni", "int", ints);
   }
   
   @Test
@@ -129,9 +138,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testIntPointFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni", "42");
-    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns", "42");
-    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns_mv", "42", "666");
+    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni", toStringArray(getRandomInts(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns", toStringArray(getRandomInts(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns_mv", toStringArray(getRandomInts(numValues, false)));
   }
   
   @Test
@@ -162,8 +172,8 @@ public class TestPointFields extends SolrTestCaseJ4 {
     for (String r : Arrays.asList("*_p_i_ni", "*_p_i_ni_ns")) {
       assertTrue(r, regexToTest.remove(r));
       String field = r.replace("*", "number");
-      doTestPointFieldSortError(field, "w/o docValues", "42");
-      doTestPointFieldFunctionQueryError(field, "w/o docValues", "42");
+      doTestPointFieldSortError(field, "w/o docValues", toStringArray(getRandomInts(1, false)));
+      doTestPointFieldFunctionQueryError(field, "w/o docValues", toStringArray(getRandomInts(1, false)));
     }
     
     for (String r : Arrays.asList("*_p_i_mv", "*_p_i_ni_mv", "*_p_i_ni_mv_dv", "*_p_i_ni_dv_ns_mv",
@@ -172,10 +182,11 @@ public class TestPointFields extends SolrTestCaseJ4 {
                                   "*_p_i_mv_sml", "*_p_i_mv_dv_sml", "*_p_i_ni_mv_dv_sml")) {
       assertTrue(r, regexToTest.remove(r));
       String field = r.replace("*", "number");
-      doTestPointFieldSortError(field, "multivalued", "42");
-      doTestPointFieldSortError(field, "multivalued", "42", "666");
-      doTestPointFieldFunctionQueryError(field, "multivalued", "42");
-      doTestPointFieldFunctionQueryError(field, "multivalued", "42", "666");
+      doTestPointFieldSortError(field, "multivalued", toStringArray(getRandomInts(1, false)));
+      int numValues = 2 * RANDOM_MULTIPLIER;
+      doTestPointFieldSortError(field, "multivalued", toStringArray(getRandomInts(numValues, false)));
+      doTestPointFieldFunctionQueryError(field, "multivalued", toStringArray(getRandomInts(1, false)));
+      doTestPointFieldFunctionQueryError(field, "multivalued", toStringArray(getRandomInts(numValues, false)));
    }
     
     assertEquals("Missing types in the test", Collections.<String>emptySet(), regexToTest);
@@ -184,68 +195,214 @@ public class TestPointFields extends SolrTestCaseJ4 {
   @Test
   public void testIntPointFieldFacetField() throws Exception {
     testPointFieldFacetField("number_p_i", "number_p_i_dv", getSequentialStringArrayWithInts(10));
+    clearIndex();
+    assertU(commit());
+    testPointFieldFacetField("number_p_i", "number_p_i_dv", toStringArray(getRandomInts(10, false)));
   }
 
   @Test
   public void testIntPointFieldRangeFacet() throws Exception {
-    doTestIntPointFieldRangeFacet("number_p_i_dv", "number_p_i");
+    String docValuesField = "number_p_i_dv";
+    String nonDocValuesField = "number_p_i";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Integer> values;
+    List<Integer> sortedValues;
+    int max;
+    do {
+      values = getRandomInts(numValues, false);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+    } while ((max = sortedValues.get(sortedValues.size() - 1)) >= Integer.MAX_VALUE - numValues); // leave room for rounding 
+    int min = sortedValues.get(0);
+    int gap = (int)(((long)(max + numValues) - (long)min) / (long)numBuckets);
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    int minBucketVal = min;
+    for (Integer value : sortedValues) {
+      while (((long)value - (long)minBucketVal) >= (long)gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i), docValuesField, String.valueOf(values.get(i)), nonDocValuesField, String.valueOf(values.get(i))));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap)),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
   }
 
   @Test
   public void testIntPointStats() throws Exception {
-    testPointStats("number_p_i", "number_p_i_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
-        0D, 9D, "10", "1", 0D);
-    testPointStats("number_p_i", "number_p_i_mv_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
-        0D, 9D, "10", "1", 0D);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    // don't produce numbers with exponents, since XPath comparison operators can't handle them
+    List<Integer> values  = getRandomInts(numValues, false, 9999999);
+    System.err.println(Arrays.toString(values.toArray(new Integer[values.size()])));
+    List<Integer> sortedValues = values.stream().sorted().collect(Collectors.toList());
+    double min = (double)sortedValues.get(0);
+    double max = (double)sortedValues.get(sortedValues.size() - 1);
+
+    String[] valArray = toStringArray(values);
+    testPointStats("number_p_i", "number_p_i_dv", valArray, min, max, numValues, 1, 0D);
+    testPointStats("number_p_i", "number_p_i_mv_dv", valArray, min, max, numValues, 1, 0D);
   }
 
   @Test
   public void testIntPointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_i_mv", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedExactQuery("number_p_i_ni_mv_dv", getSequentialStringArrayWithInts(20));
+    String[] ints = toStringArray(getRandomInts(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_i_mv", ints);
+    testPointFieldMultiValuedExactQuery("number_p_i_ni_mv_dv", ints);
   }
 
   @Test
   public void testIntPointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_i_ni_mv", getSequentialStringArrayWithInts(20), false);
-    testPointFieldMultiValuedExactQuery("number_p_i_ni_ns_mv", getSequentialStringArrayWithInts(20), false);
+    String[] ints = toStringArray(getRandomInts(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_i_ni_mv", ints, false);
+    testPointFieldMultiValuedExactQuery("number_p_i_ni_ns_mv", ints, false);
   }
   
   @Test
   public void testIntPointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_i_mv", "int", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedReturn("number_p_i_ni_mv_dv", "int", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedReturn("number_p_i_dv_ns_mv", "int", getSequentialStringArrayWithInts(20));
+    String[] ints = toStringArray(getRandomInts(20, false));
+    testPointFieldMultiValuedReturn("number_p_i_mv", "int", ints);
+    testPointFieldMultiValuedReturn("number_p_i_ni_mv_dv", "int", ints);
+    testPointFieldMultiValuedReturn("number_p_i_dv_ns_mv", "int", ints);
   }
   
   @Test
   public void testIntPointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_i_mv", "int", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedRangeQuery("number_p_i_ni_mv_dv", "int", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedRangeQuery("number_p_i_mv_dv", "int", getSequentialStringArrayWithInts(20));
+    String[] ints = toStringArray(getRandomInts(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_i_mv", "int", ints);
+    testPointFieldMultiValuedRangeQuery("number_p_i_ni_mv_dv", "int", ints);
+    testPointFieldMultiValuedRangeQuery("number_p_i_mv_dv", "int", ints);
   }
   
   @Test
   public void testIntPointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_i_ni", getSequentialStringArrayWithInts(10));
-    doTestFieldNotIndexed("number_p_i_ni_mv", getSequentialStringArrayWithInts(10));
+    String[] ints = toStringArray(getRandomInts(10, false));
+    doTestFieldNotIndexed("number_p_i_ni", ints);
+    doTestFieldNotIndexed("number_p_i_ni_mv", ints);
   }
   
   //TODO MV SORT?
   @Test
   public void testIntPointFieldMultiValuedFacetField() throws Exception {
     testPointFieldMultiValuedFacetField("number_p_i_mv", "number_p_i_mv_dv", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedFacetField("number_p_i_mv", "number_p_i_mv_dv", toStringArray(getRandomInts(20, false)));
+    String[] randomSortedInts = toStringArray(getRandomInts(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedFacetField("number_p_i_mv", "number_p_i_mv_dv", randomSortedInts);
   }
 
   @Test
   public void testIntPointFieldMultiValuedRangeFacet() throws Exception {
-    doTestIntPointFieldMultiValuedRangeFacet("number_p_i_mv_dv", "number_p_i_mv");
+    String docValuesField = "number_p_i_mv_dv";
+    String nonDocValuesField = "number_p_i_mv";
+    int numValues = 20 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Integer> values;
+    List<PosVal<Integer>> sortedValues;
+    int max;
+    do {
+      values = getRandomInts(numValues, false);
+      sortedValues = toAscendingPosVals(values, true);
+    } while ((max = sortedValues.get(sortedValues.size() - 1).val) >= Integer.MAX_VALUE - numValues); // leave room for rounding
+    int min = sortedValues.get(0).val;
+    int gap = (int)(((long)(max + numValues) - (long)min) / (long)numBuckets);
+    List<Set<Integer>> docIdBucket = new ArrayList<>(numBuckets);
+    for (int i = 0 ; i < numBuckets ; ++i) {
+      docIdBucket.add(new HashSet<>());
+    }
+    int bucketNum = 0;
+    int minBucketVal = min;
+    for (PosVal<Integer> value : sortedValues) {
+      while (value.val - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+      }
+      docIdBucket.get(bucketNum).add(value.pos / 2); // each doc gets two consecutive values 
+    }
+    for (int i = 0 ; i < numValues ; i += 2) {
+      assertU(adoc("id", String.valueOf(i / 2),
+          docValuesField, String.valueOf(values.get(i)),
+          docValuesField, String.valueOf(values.get(i + 1)),
+          nonDocValuesField, String.valueOf(values.get(i)),
+          nonDocValuesField, String.valueOf(values.get(i + 1))));
+    }
+    assertU(commit());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    minBucketVal = min;
+    testStrings[numBuckets] = "//*[@numFound='" + (numValues / 2) + "']";
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + docIdBucket.get(i).size() + "']";
+    }
+
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "indent", "on"),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv", "indent", "on"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + docIdBucket.get(i).size() + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter", "indent", "on"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv", "indent", "on"),
+        testStrings);
   }
 
   @Test
-  public void testIntPointMultiValuedFunctionQuery() throws Exception {
+  public void testIntPointMultiValuedFunctionQuery() throws Exception {       
     testPointMultiValuedFunctionQuery("number_p_i_mv", "number_p_i_mv_dv", "int", getSequentialStringArrayWithInts(20));
+    testPointMultiValuedFunctionQuery("number_p_i_mv", "number_p_i_mv_dv", "int",
+        toStringArray(getRandomInts(20, false).stream().sorted().collect(Collectors.toList())));
   }
   
   @Test
@@ -280,6 +437,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
       this.pos = pos;
       this.val = val;
     }
+    public String toString() {
+      return "(" + pos + ": " + val.toString() + ")";
+    }
   }
 
   /** Primary sort by value, with nulls either first or last as specified, and then secondary sort by position. */
@@ -345,33 +505,29 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDoublePointFieldExactQuery() throws Exception {
-    doTestFloatPointFieldExactQuery("number_d");
-    doTestFloatPointFieldExactQuery("number_p_d");
-    doTestFloatPointFieldExactQuery("number_p_d_mv");
-    doTestFloatPointFieldExactQuery("number_p_d_dv");
-    doTestFloatPointFieldExactQuery("number_p_d_mv_dv");
-    doTestFloatPointFieldExactQuery("number_p_d_ni_dv");
-    doTestFloatPointFieldExactQuery("number_p_d_ni_ns_dv");
-    doTestFloatPointFieldExactQuery("number_p_d_ni_dv_ns");
-    doTestFloatPointFieldExactQuery("number_p_d_ni_mv_dv");
+    doTestFloatPointFieldExactQuery("number_d", true);
+    doTestFloatPointFieldExactQuery("number_p_d", true);
+    doTestFloatPointFieldExactQuery("number_p_d_mv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_dv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_mv_dv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_dv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_ns_dv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_dv_ns", true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_mv_dv", true);
   }
   
   @Test
   public void testDoublePointFieldNonSearchableExactQuery() throws Exception {
-    doTestFloatPointFieldExactQuery("number_p_d_ni", false);
-    doTestFloatPointFieldExactQuery("number_p_d_ni_ns", false);
+    doTestFloatPointFieldExactQuery("number_p_d_ni", false, true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_ns", false, true);
   }
  
   @Test
   public void testDoublePointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_d", "double", new String[]{"0.0", "1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
-    testPointFieldReturn("number_p_d_dv_ns", "double", new String[]{"0.0", "1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
-    String[] arr = new String[atLeast(10)];
-    for (int i = 0; i < arr.length; i++) {
-      double rand = random().nextDouble() * 10;
-      arr[i] = String.valueOf(rand);
-    }
-    testPointFieldReturn("number_p_d", "double", arr);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] doubles = toStringArray(getRandomDoubles(numValues, false));
+    testPointFieldReturn("number_p_d", "double", doubles);
+    testPointFieldReturn("number_p_d_dv_ns", "double", doubles);
   }
   
   @Test
@@ -383,9 +539,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testDoubleFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni", "42.3");
-    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns", "42.3");
-    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns_mv", "42.3", "-66.6");
+    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni", toStringArray(getRandomDoubles(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns", toStringArray(getRandomDoubles(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns_mv", toStringArray(getRandomDoubles(numValues, false)));
   }
   
   
@@ -446,41 +603,121 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDoublePointFieldRangeFacet() throws Exception {
-    doTestFloatPointFieldRangeFacet("number_p_d_dv", "number_p_d");
+    String docValuesField = "number_p_d_dv";
+    String nonDocValuesField = "number_p_d";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Double> values, sortedValues;
+    double min, max, gap, buffer;
+    do {
+      values = getRandomDoubles(numValues, false);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+      min = sortedValues.get(0);
+      max = sortedValues.get(sortedValues.size() - 1);
+      buffer = BigDecimal.valueOf(max).subtract(BigDecimal.valueOf(min))
+          .divide(BigDecimal.valueOf(numValues), RoundingMode.HALF_UP)
+          .divide(BigDecimal.valueOf(2.0D), RoundingMode.HALF_UP).doubleValue();
+      gap = BigDecimal.valueOf(max + buffer).subtract(BigDecimal.valueOf(min - buffer))
+          .divide(BigDecimal.valueOf(numBuckets), RoundingMode.HALF_UP).doubleValue();
+    } while (max >= Double.MAX_VALUE - buffer || min <= -Double.MAX_VALUE + buffer);
+    // System.err.println("min: " + min + "   max: " + max + "   gap: " + gap + "   buffer: " + buffer);
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    double minBucketVal = min - buffer;
+    // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + minBucketVal);
+    for (double value : sortedValues) {
+      // System.err.println("value: " + value);
+      while (value - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+        // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + minBucketVal);
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i),
+          docValuesField, String.valueOf(values.get(i)), nonDocValuesField, String.valueOf(values.get(i))));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min - buffer;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap)),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min - buffer;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
   }
 
   @Test
   public void testDoublePointStats() throws Exception {
-    testPointStats("number_p_d", "number_p_d_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-        -10.0D, 9.9D, "10", "1", 1E-10D);
-    testPointStats("number_p_d_mv", "number_p_d_mv_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-        -10.0D, 9.9D, "10", "1", 1E-10D);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    // don't produce numbers with exponents, since XPath comparison operators can't handle them: 7 digits of precision
+    List<Float> values  = getRandomInts(numValues, false, 9999999).stream()
+        .map(v -> (float)((double)v * Math.pow(10D, -1 * random().nextInt(8)))).collect(Collectors.toList());
+    System.err.println(Arrays.toString(values.toArray(new Float[values.size()])));
+    List<Float> sortedValues = values.stream().sorted().collect(Collectors.toList());
+    double min = (double)sortedValues.get(0);
+    double max = (double)sortedValues.get(sortedValues.size() - 1);
+
+    String[] valArray = toStringArray(values);
+    testPointStats("number_p_d", "number_p_d_dv", valArray, min, max, numValues, 1, 1E-7D);
+    testPointStats("number_p_d", "number_p_d_mv_dv", valArray, min, max, numValues, 1, 1E-7D);
   }
   
   @Test
   public void testDoublePointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_d_mv", toStringArray(getRandomDoubles(20, false)));
-    testPointFieldMultiValuedExactQuery("number_p_d_ni_mv_dv", toStringArray(getRandomDoubles(20, false)));
+    String[] doubles = toStringArray(getRandomDoubles(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_d_mv", doubles);
+    testPointFieldMultiValuedExactQuery("number_p_d_ni_mv_dv", doubles);
   }
   
   @Test
   public void testDoublePointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_d_ni_mv", toStringArray(getRandomDoubles(20, false)), false);
-    testPointFieldMultiValuedExactQuery("number_p_d_ni_ns_mv", toStringArray(getRandomDoubles(20, false)), false);
+    String[] doubles = toStringArray(getRandomDoubles(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_d_ni_mv", doubles, false);
+    testPointFieldMultiValuedExactQuery("number_p_d_ni_ns_mv", doubles, false);
   }
   
   @Test
   public void testDoublePointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_d_mv", "double", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedReturn("number_p_d_ni_mv_dv", "double", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedReturn("number_p_d_dv_ns_mv", "double", getSequentialStringArrayWithDoubles(20));
+    String[] doubles = toStringArray(getRandomDoubles(20, false));
+    testPointFieldMultiValuedReturn("number_p_d_mv", "double", doubles);
+    testPointFieldMultiValuedReturn("number_p_d_ni_mv_dv", "double", doubles);
+    testPointFieldMultiValuedReturn("number_p_d_dv_ns_mv", "double", doubles);
   }
   
   @Test
   public void testDoublePointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_d_mv", "double", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedRangeQuery("number_p_d_ni_mv_dv", "double", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedRangeQuery("number_p_d_mv_dv", "double", getSequentialStringArrayWithDoubles(20));
+    String[] doubles = toStringArray(getRandomDoubles(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_d_mv", "double", doubles);
+    testPointFieldMultiValuedRangeQuery("number_p_d_ni_mv_dv", "double", doubles);
+    testPointFieldMultiValuedRangeQuery("number_p_d_mv_dv", "double", doubles);
   }
   
   @Test
@@ -522,8 +759,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testDoublePointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_d_ni", getSequentialStringArrayWithDoubles(10));
-    doTestFieldNotIndexed("number_p_d_ni_mv", getSequentialStringArrayWithDoubles(10));
+    String[] doubles = toStringArray(getRandomDoubles(10, false));
+    doTestFieldNotIndexed("number_p_d_ni", doubles);
+    doTestFieldNotIndexed("number_p_d_ni_mv", doubles);
   }
   
   
@@ -571,32 +809,28 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testFloatPointFieldExactQuery() throws Exception {
-    doTestFloatPointFieldExactQuery("number_p_f");
-    doTestFloatPointFieldExactQuery("number_p_f_mv");
-    doTestFloatPointFieldExactQuery("number_p_f_dv");
-    doTestFloatPointFieldExactQuery("number_p_f_mv_dv");
-    doTestFloatPointFieldExactQuery("number_p_f_ni_dv");
-    doTestFloatPointFieldExactQuery("number_p_f_ni_ns_dv");
-    doTestFloatPointFieldExactQuery("number_p_f_ni_dv_ns");
-    doTestFloatPointFieldExactQuery("number_p_f_ni_mv_dv");
+    doTestFloatPointFieldExactQuery("number_p_f", false);
+    doTestFloatPointFieldExactQuery("number_p_f_mv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_dv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_mv_dv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_dv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_ns_dv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_dv_ns", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_mv_dv", false);
   }
   
   @Test
   public void testFloatPointFieldNonSearchableExactQuery() throws Exception {
-    doTestFloatPointFieldExactQuery("number_p_f_ni", false);
-    doTestFloatPointFieldExactQuery("number_p_f_ni_ns", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni", false, false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_ns", false, false);
   }
   
   @Test
   public void testFloatPointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_f", "float", new String[]{"0.0", "-1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
-    testPointFieldReturn("number_p_f_dv_ns", "float", new String[]{"0.0", "-1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
-    String[] arr = new String[atLeast(10)];
-    for (int i = 0; i < arr.length; i++) {
-      float rand = random().nextFloat() * 10;
-      arr[i] = String.valueOf(rand);
-    }
-    testPointFieldReturn("number_p_f", "float", arr);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] floats = toStringArray(getRandomFloats(numValues, false));
+    testPointFieldReturn("number_p_f", "float", floats);
+    testPointFieldReturn("number_p_f_dv_ns", "float", floats);
   }
   
   @Test
@@ -608,9 +842,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testFloatPointFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni", "42.3");
-    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns", "42.3");
-    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns_mv", "42.3", "-66.6");
+    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni", toStringArray(getRandomFloats(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns", toStringArray(getRandomFloats(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns_mv", toStringArray(getRandomFloats(numValues, false)));
   }
   
   @Test
@@ -669,42 +904,120 @@ public class TestPointFields extends SolrTestCaseJ4 {
   }
 
   @Test
+  @AwaitsFix(bugUrl = "https://issues.apache.org/jira/browse/SOLR-11043")
   public void testFloatPointFieldRangeFacet() throws Exception {
-    doTestFloatPointFieldRangeFacet("number_p_f_dv", "number_p_f");
+    String docValuesField = "number_p_f_dv";
+    String nonDocValuesField = "number_p_f";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Float> values, sortedValues;
+    float min, max, gap, buffer;
+    do {
+      values = getRandomFloats(numValues, false);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+      min = sortedValues.get(0);
+      max = sortedValues.get(sortedValues.size() - 1);
+      buffer = (float)(((double)max - (double)min) / (double)numValues / 2.0D);
+      gap = (float)(((double)max + (double)buffer - (double)min + (double)buffer) / (double)numBuckets);
+    } while (max >= Float.MAX_VALUE - buffer || min <= -Float.MAX_VALUE + buffer); 
+    // System.err.println("min: " + min + "   max: " + max + "   gap: " + gap + "   buffer: " + buffer);
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    float minBucketVal = min - buffer;
+    // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + minBucketVal);
+    for (float value : sortedValues) {
+      // System.err.println("value: " + value);
+      while (value - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+        // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + minBucketVal);
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i), 
+          docValuesField, String.valueOf(values.get(i)), nonDocValuesField, String.valueOf(values.get(i))));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min - buffer;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap)),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min - buffer;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
   }
 
   @Test
   public void testFloatPointStats() throws Exception {
-    testPointStats("number_p_f", "number_p_f_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-        -10D, 9.9D, "10", "1", 1E-6D);
-    testPointStats("number_p_f_mv", "number_p_f_mv_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-        -10D, 9.9D, "10", "1", 1E-6D);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    // don't produce numbers with exponents, since XPath comparison operators can't handle them: 7 digits of precision
+    List<Float> values  = getRandomInts(numValues, false, 9999999).stream()
+        .map(v -> (float)((double)v * Math.pow(10D, -1 * random().nextInt(8)))).collect(Collectors.toList());
+    System.err.println(Arrays.toString(values.toArray(new Float[values.size()])));
+    List<Float> sortedValues = values.stream().sorted().collect(Collectors.toList());
+    double min = (double)sortedValues.get(0);
+    double max = (double)sortedValues.get(sortedValues.size() - 1);
+
+    String[] valArray = toStringArray(values);
+    testPointStats("number_p_f", "number_p_f_dv", valArray, min, max, numValues, 1, 1E-7D);
+    testPointStats("number_p_f", "number_p_f_mv_dv", valArray, min, max, numValues, 1, 1E-7D);
   }
   
   @Test
   public void testFloatPointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_f_mv", toStringArray(getRandomFloats(20, false)));
-    testPointFieldMultiValuedExactQuery("number_p_f_ni_mv_dv", toStringArray(getRandomFloats(20, false)));
+    String[] floats = toStringArray(getRandomFloats(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_f_mv", floats);
+    testPointFieldMultiValuedExactQuery("number_p_f_ni_mv_dv", floats);
   }
   
   @Test
   public void testFloatPointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_f_ni_mv", toStringArray(getRandomFloats(20, false)), false);
-    testPointFieldMultiValuedExactQuery("number_p_f_ni_ns_mv", toStringArray(getRandomFloats(20, false)), false);
+    String[] floats = toStringArray(getRandomFloats(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_f_ni_mv", floats, false);
+    testPointFieldMultiValuedExactQuery("number_p_f_ni_ns_mv", floats, false);
   }
   
   @Test
   public void testFloatPointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_f_mv", "float", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedReturn("number_p_f_ni_mv_dv", "float", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedReturn("number_p_f_dv_ns_mv", "float", getSequentialStringArrayWithDoubles(20));
+    String[] floats = toStringArray(getRandomFloats(20, false));
+    testPointFieldMultiValuedReturn("number_p_f_mv", "float", floats);
+    testPointFieldMultiValuedReturn("number_p_f_ni_mv_dv", "float", floats);
+    testPointFieldMultiValuedReturn("number_p_f_dv_ns_mv", "float", floats);
   }
   
   @Test
   public void testFloatPointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_f_mv", "float", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedRangeQuery("number_p_f_ni_mv_dv", "float", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedRangeQuery("number_p_f_mv_dv", "float", getSequentialStringArrayWithDoubles(20));
+    String[] floats = toStringArray(getRandomFloats(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_f_mv", "float", floats);
+    testPointFieldMultiValuedRangeQuery("number_p_f_ni_mv_dv", "float", floats);
+    testPointFieldMultiValuedRangeQuery("number_p_f_mv_dv", "float", floats);
   }
   
   @Test
@@ -754,8 +1067,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testFloatPointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_f_ni", getSequentialStringArrayWithDoubles(10));
-    doTestFieldNotIndexed("number_p_f_ni_mv", getSequentialStringArrayWithDoubles(10));
+    String[] floats = toStringArray(getRandomFloats(10, false));
+    doTestFieldNotIndexed("number_p_f_ni", floats);
+    doTestFieldNotIndexed("number_p_f_ni_mv", floats);
   }
   
   // Long
@@ -780,8 +1094,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_l", "long", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99", String.valueOf(Long.MAX_VALUE)});
-    testPointFieldReturn("number_p_l_dv_ns", "long", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99", String.valueOf(Long.MAX_VALUE)});
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] longs = toStringArray(getRandomLongs(numValues, false));
+    testPointFieldReturn("number_p_l", "long", longs);
+    testPointFieldReturn("number_p_l_dv_ns", "long", longs);
   }
   
   @Test
@@ -793,9 +1109,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni", "3333333333");
-    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns", "3333333333");
-    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns_mv", "3333333333", "-4444444444");
+    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni", toStringArray(getRandomLongs(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns", toStringArray(getRandomLongs(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns_mv", toStringArray(getRandomLongs(numValues, false)));
   }
 
   @Test
@@ -828,8 +1145,8 @@ public class TestPointFields extends SolrTestCaseJ4 {
     for (String r : Arrays.asList("*_p_l_ni", "*_p_l_ni_ns")) {
       assertTrue(r, regexToTest.remove(r));
       String field = r.replace("*", "number");
-      doTestPointFieldSortError(field, "w/o docValues", "4234");
-      doTestPointFieldFunctionQueryError(field, "w/o docValues", "4234");
+      doTestPointFieldSortError(field, "w/o docValues", toStringArray(getRandomLongs(1, false)));
+      doTestPointFieldFunctionQueryError(field, "w/o docValues", toStringArray(getRandomLongs(1, false)));
     }
     
     for (String r : Arrays.asList("*_p_l_mv", "*_p_l_ni_mv", "*_p_l_ni_mv_dv", "*_p_l_ni_dv_ns_mv",
@@ -838,10 +1155,11 @@ public class TestPointFields extends SolrTestCaseJ4 {
                                   "*_p_l_mv_sml", "*_p_l_mv_dv_sml", "*_p_l_ni_mv_dv_sml")) {
       assertTrue(r, regexToTest.remove(r));
       String field = r.replace("*", "number");
-      doTestPointFieldSortError(field, "multivalued", "4234");
-      doTestPointFieldSortError(field, "multivalued", "4234", "66666666");
-      doTestPointFieldFunctionQueryError(field, "multivalued", "4234");
-      doTestPointFieldFunctionQueryError(field, "multivalued", "4234", "66666666");
+      doTestPointFieldSortError(field, "multivalued", toStringArray(getRandomLongs(1, false)));
+      int numValues = 2 * RANDOM_MULTIPLIER;
+      doTestPointFieldSortError(field, "multivalued", toStringArray(getRandomLongs(numValues, false)));
+      doTestPointFieldFunctionQueryError(field, "multivalued", toStringArray(getRandomLongs(1, false)));
+      doTestPointFieldFunctionQueryError(field, "multivalued", toStringArray(getRandomLongs(numValues, false)));
     }
     
     assertEquals("Missing types in the test", Collections.<String>emptySet(), regexToTest);
@@ -857,41 +1175,111 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldRangeFacet() throws Exception {
-    doTestIntPointFieldRangeFacet("number_p_l_dv", "number_p_l");
+    String docValuesField = "number_p_l_dv";
+    String nonDocValuesField = "number_p_l";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Long> values;
+    List<Long> sortedValues;
+    long max;
+    do {
+      values = getRandomLongs(numValues, false);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+    } while ((max = sortedValues.get(sortedValues.size() - 1)) >= Integer.MAX_VALUE - numValues); // leave room for rounding 
+    long min = sortedValues.get(0);
+    long gap = BigInteger.valueOf(max + numValues).subtract(BigInteger.valueOf(min))
+        .divide(BigInteger.valueOf(numBuckets)).longValueExact();
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    long minBucketVal = min;
+    for (Long value : sortedValues) {
+      while (value - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i), docValuesField, String.valueOf(values.get(i)), nonDocValuesField, String.valueOf(values.get(i))));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap)),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
   }
   
   @Test
   public void testLongPointStats() throws Exception {
-    testPointStats("number_p_l", "number_p_l_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
-        0D, 9D, "10", "1", 0D);
-    testPointStats("number_p_l_mv", "number_p_l_mv_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
-        0D, 9D, "10", "1", 0D);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    // don't produce numbers with exponents, since XPath comparison operators can't handle them
+    List<Long> values  = getRandomLongs(numValues, false, 9999999L);
+    List<Long> sortedValues = values.stream().sorted().collect(Collectors.toList());
+    double min = (double)sortedValues.get(0);
+    double max = (double)sortedValues.get(sortedValues.size() - 1);
+
+    String[] valArray = toStringArray(values);
+    testPointStats("number_p_l", "number_p_l_dv", valArray, min, max, numValues, 1, 0D);
+    testPointStats("number_p_l", "number_p_l_mv_dv", valArray, min, max, numValues, 1, 0D);
   }
   
   @Test
   public void testLongPointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_l_mv", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedExactQuery("number_p_l_ni_mv_dv", getSequentialStringArrayWithInts(20));
+    String[] ints = toStringArray(getRandomInts(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_l_mv", ints);
+    testPointFieldMultiValuedExactQuery("number_p_l_ni_mv_dv", ints);
   }
   
   @Test
   public void testLongPointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_l_ni_mv", getSequentialStringArrayWithInts(20), false);
-    testPointFieldMultiValuedExactQuery("number_p_l_ni_ns_mv", getSequentialStringArrayWithInts(20), false);
+    String[] longs = toStringArray(getRandomLongs(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_l_ni_mv", longs, false);
+    testPointFieldMultiValuedExactQuery("number_p_l_ni_ns_mv", longs, false);
   }
   
   @Test
   public void testLongPointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_l_mv", "long", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedReturn("number_p_l_ni_mv_dv", "long", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedReturn("number_p_l_dv_ns_mv", "long", getSequentialStringArrayWithInts(20));
+    String[] longs = toStringArray(getRandomLongs(20, false));
+    testPointFieldMultiValuedReturn("number_p_l_mv", "long", longs);
+    testPointFieldMultiValuedReturn("number_p_l_ni_mv_dv", "long", longs);
+    testPointFieldMultiValuedReturn("number_p_l_dv_ns_mv", "long", longs);
   }
   
   @Test
   public void testLongPointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_l_mv", "long", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedRangeQuery("number_p_l_ni_mv_dv", "long", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedRangeQuery("number_p_l_mv_dv", "long", getSequentialStringArrayWithInts(20));
+    String[] longs = toStringArray(getRandomLongs(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_l_mv", "long", longs);
+    testPointFieldMultiValuedRangeQuery("number_p_l_ni_mv_dv", "long", longs);
+    testPointFieldMultiValuedRangeQuery("number_p_l_mv_dv", "long", longs);
   }
   
   @Test
@@ -902,7 +1290,77 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldMultiValuedRangeFacet() throws Exception {
-    doTestIntPointFieldMultiValuedRangeFacet("number_p_l_mv_dv", "number_p_l_mv");
+    String docValuesField = "number_p_l_mv_dv";
+    String nonDocValuesField = "number_p_l_mv";
+    int numValues = 20 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Long> values;
+    List<PosVal<Long>> sortedValues;
+    long max;
+    do {
+      values = getRandomLongs(numValues, false);
+      sortedValues = toAscendingPosVals(values, true);
+    } while ((max = sortedValues.get(sortedValues.size() - 1).val) >= Long.MAX_VALUE - numValues); // leave room for rounding 
+    long min = sortedValues.get(0).val;
+    long gap = BigInteger.valueOf(max + numValues).subtract(BigInteger.valueOf(min))
+        .divide(BigInteger.valueOf(numBuckets)).longValueExact();
+    List<Set<Integer>> docIdBucket = new ArrayList<>(numBuckets);
+    for (int i = 0 ; i < numBuckets ; ++i) {
+      docIdBucket.add(new HashSet<>());
+    }
+    int bucketNum = 0;
+    long minBucketVal = min;
+    for (PosVal<Long> value : sortedValues) {
+      while (value.val - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+      }
+      docIdBucket.get(bucketNum).add(value.pos / 2); // each doc gets two consecutive values 
+    }
+    for (int i = 0 ; i < numValues ; i += 2) {
+      assertU(adoc("id", String.valueOf(i / 2),
+          docValuesField, String.valueOf(values.get(i)),
+          docValuesField, String.valueOf(values.get(i + 1)),
+          nonDocValuesField, String.valueOf(values.get(i)),
+          nonDocValuesField, String.valueOf(values.get(i + 1))));
+    }
+    assertU(commit());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + (numValues / 2) + "']";
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + docIdBucket.get(i).size() + "']";
+    }
+
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "indent", "on"),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv", "indent", "on"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + docIdBucket.get(i).size() + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter", "indent", "on"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv", "indent", "on"),
+        testStrings);
   }
   
   @Test
@@ -939,8 +1397,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_l_ni", getSequentialStringArrayWithInts(10));
-    doTestFieldNotIndexed("number_p_l_ni_mv", getSequentialStringArrayWithInts(10));
+    String[] longs = toStringArray(getRandomLongs(10, false));
+    doTestFieldNotIndexed("number_p_l_ni", longs);
+    doTestFieldNotIndexed("number_p_l_ni_mv", longs);
   }
 
   // Date
@@ -964,12 +1423,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDatePointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_dt", "date",
-        new String[]{"1995-12-31T23:59:59Z", "1994-02-28T23:59:59Z",
-            "2015-12-31T23:59:59Z", "2000-10-31T23:59:59Z", "1999-12-31T12:59:59Z"});
-    testPointFieldReturn("number_p_dt_dv_ns", "date",
-        new String[]{"1995-12-31T23:59:59Z", "1994-02-28T23:59:59Z",
-            "2015-12-31T23:59:59Z", "2000-10-31T23:59:59Z", "1999-12-31T12:59:59Z"});
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] dates = toStringArray(getRandomInstants(numValues, false));
+    testPointFieldReturn("number_p_dt", "date", dates);
+    testPointFieldReturn("number_p_dt_dv_ns", "date", dates);
   }
 
   @Test
@@ -980,9 +1437,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testDatePointFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni", "1995-12-31T23:59:59Z");
-    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns", "1995-12-31T23:59:59Z");
-    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns_mv", "1995-12-31T23:59:59Z", "2000-10-31T23:59:59Z");
+    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni", toStringArray(getRandomInstants(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns", toStringArray(getRandomInstants(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns_mv", toStringArray(getRandomInstants(numValues, false)));
   }
 
   @Test
@@ -1037,12 +1495,147 @@ public class TestPointFields extends SolrTestCaseJ4 {
     testPointFieldFacetField("number_p_dt", "number_p_dt_dv", getSequentialStringArrayWithDates(10));
     clearIndex();
     assertU(commit());
-    testPointFieldFacetField("number_p_dt", "number_p_dt_dv", getSequentialStringArrayWithDates(10));
-  }
+    testPointFieldFacetField("number_p_dt", "number_p_dt_dv", toStringArray(getRandomInstants(10, false)));
+  }
+
+  private static class DateGapCeiling {
+    String calendarUnit = "MILLIS";
+    long inCalendarUnits;
+    boolean negative = false;
+  
+    /** Maximize calendar unit size given initialGapMillis; performs ceiling on each conversion */
+    DateGapCeiling(long initialGapMillis) {
+      negative = initialGapMillis < 0;
+      inCalendarUnits = Math.abs(initialGapMillis);
+      if (inCalendarUnits >= 1000L) {
+        calendarUnit = "SECS";
+        inCalendarUnits = (inCalendarUnits + 999L) / 1000L;
+        if (inCalendarUnits >= 60L) {
+          calendarUnit = "MINUTES";
+          inCalendarUnits = (inCalendarUnits + 59L) / 60L;
+          if (inCalendarUnits >= 60L) {
+            calendarUnit = "HOURS";
+            inCalendarUnits = (inCalendarUnits + 59L) / 60L;
+            if (inCalendarUnits >= 24L) {
+              calendarUnit = "DAYS";
+              inCalendarUnits = (inCalendarUnits + 23L) / 24L;
+              if (inCalendarUnits >= 12L) {
+                calendarUnit = "MONTHS";
+                inCalendarUnits = (inCalendarUnits + 11L) / 12L;
+                if ((inCalendarUnits * 16) >= 487) {  // 487 = 365.25 / 12 * 16   (365.25 days/year, -ish)
+                  calendarUnit = "YEARS";
+                  inCalendarUnits = (16L * inCalendarUnits + 486) / 487L; 
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    @Override
+    public String toString() {
+      return (negative ? "-" : "+") + inCalendarUnits + calendarUnit;
+    }
 
+    public long addTo(long millis) {  // Instant.plus() doesn't work with estimated durations (MONTHS and YEARS)
+      LocalDateTime time = LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneOffset.ofHours(0));
+      if (negative) {
+        time = time.minus(inCalendarUnits, DateMathParser.CALENDAR_UNITS.get(calendarUnit));
+      } else {
+        time = time.plus(inCalendarUnits, DateMathParser.CALENDAR_UNITS.get(calendarUnit));
+      }
+      return time.atZone(ZoneOffset.ofHours(0)).toInstant().toEpochMilli();
+    }
+  }
+  
   @Test
   public void testDatePointFieldRangeFacet() throws Exception {
-    doTestDatePointFieldRangeFacet("number_p_dt_dv", "number_p_dt");
+    String docValuesField = "number_p_dt_dv";
+    String nonDocValuesField = "number_p_dt";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Long> values, sortedValues;
+    long min, max;
+    DateGapCeiling gap;
+    do {
+      values = getRandomLongs(numValues, false, MAX_DATE_EPOCH_MILLIS);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+      min = sortedValues.get(0);
+      max = sortedValues.get(sortedValues.size() - 1);
+    } while (max > MAX_DATE_EPOCH_MILLIS || min <= MIN_DATE_EPOCH_MILLIS);
+    long initialGap = BigInteger.valueOf(max).subtract(BigInteger.valueOf(min))
+        .divide(BigInteger.valueOf(numBuckets)).longValueExact();
+    gap = new DateGapCeiling(BigInteger.valueOf(max + initialGap).subtract(BigInteger.valueOf(min)) // padding for rounding
+        .divide(BigInteger.valueOf(numBuckets)).longValueExact());
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    long minBucketVal = min;
+    // System.err.println("min:" + Instant.ofEpochMilli(min) + "   max: " + Instant.ofEpochMilli(max) + "   gap: " + gap);
+    // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + Instant.ofEpochMilli(minBucketVal));
+    for (long value : sortedValues) {
+      // System.err.println("value: " + Instant.ofEpochMilli(value));
+      while (value >= gap.addTo(minBucketVal)) {
+        ++bucketNum;
+        minBucketVal = gap.addTo(minBucketVal);
+        // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + Instant.ofEpochMilli(minBucketVal));
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i), docValuesField, Instant.ofEpochMilli(values.get(i)).toString(),
+          nonDocValuesField, Instant.ofEpochMilli(values.get(i)).toString()));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + Instant.ofEpochMilli(minBucketVal).toString() 
+          + "'][.='" + bucketCount[i] + "']";
+      minBucketVal = gap.addTo(minBucketVal);
+    }
+    long maxPlusGap = gap.addTo(max);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, 
+        "facet.range.start", Instant.ofEpochMilli(min).toString(),
+        "facet.range.end", Instant.ofEpochMilli(maxPlusGap).toString(),
+        "facet.range.gap", gap.toString()),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, 
+        "facet.range.start", Instant.ofEpochMilli(min).toString(),
+        "facet.range.end", Instant.ofEpochMilli(maxPlusGap).toString(),   
+        "facet.range.gap", gap.toString(), 
+        "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + Instant.ofEpochMilli(minBucketVal).toString() 
+          + "'][.='" + bucketCount[i] + "']";
+      minBucketVal = gap.addTo(minBucketVal);
+    }
+    maxPlusGap = gap.addTo(max);
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, 
+        "facet.range.start", Instant.ofEpochMilli(min).toString(),
+        "facet.range.end", Instant.ofEpochMilli(maxPlusGap).toString(), 
+        "facet.range.gap", gap.toString(), 
+        "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, 
+        "facet.range.start", Instant.ofEpochMilli(min).toString(),
+        "facet.range.end", Instant.ofEpochMilli(maxPlusGap).toString(), 
+        "facet.range.gap", gap.toString(), 
+        "facet.range.method", "dv"),
+        testStrings);
   }
 
   @Test
@@ -1053,27 +1646,31 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDatePointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_dt_mv", getSequentialStringArrayWithDates(20));
-    testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv_dv", getSequentialStringArrayWithDates(20));
+    String[] dates = toStringArray(getRandomInstants(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_dt_mv", dates);
+    testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv_dv", dates);
   }
 
   @Test
   public void testDatePointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv", getSequentialStringArrayWithDates(20), false);
-    testPointFieldMultiValuedExactQuery("number_p_dt_ni_ns_mv", getSequentialStringArrayWithDates(20), false);
+    String[] dates = toStringArray(getRandomInstants(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv", dates, false);
+    testPointFieldMultiValuedExactQuery("number_p_dt_ni_ns_mv", dates, false);
   }
   
   @Test
   public void testDatePointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_dt_mv", "date", getSequentialStringArrayWithDates(20));
-    testPointFieldMultiValuedReturn("number_p_dt_ni_mv_dv", "date", getSequentialStringArrayWithDates(20));
-    testPointFieldMultiValuedReturn("number_p_dt_dv_ns_mv", "date", getSequentialStringArrayWithDates(20));
+    String[] dates = toStringArray(getRandomInstants(20, false));
+    testPointFieldMultiValuedReturn("number_p_dt_mv", "date", dates);
+    testPointFieldMultiValuedReturn("number_p_dt_ni_mv_dv", "date", dates);
+    testPointFieldMultiValuedReturn("number_p_dt_dv_ns_mv", "date", dates);
   }
 
   @Test
   public void testDatePointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_dt_mv", "date", getSequentialStringArrayWithDates(20));
-    testPointFieldMultiValuedRangeQuery("number_p_dt_ni_mv_dv", "date", getSequentialStringArrayWithDates(20));
+    String[] dates = toStringArray(getRandomInstants(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_dt_mv", "date", dates);
+    testPointFieldMultiValuedRangeQuery("number_p_dt_ni_mv_dv", "date", dates);
   }
 
   @Test
@@ -1089,7 +1686,8 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDatePointMultiValuedFunctionQuery() throws Exception {
-    testPointMultiValuedFunctionQuery("number_p_dt_mv", "number_p_dt_mv_dv", "date", getSequentialStringArrayWithDates(20));
+    String[] dates = toStringArray(getRandomInstants(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointMultiValuedFunctionQuery("number_p_dt_mv", "number_p_dt_mv_dv", "date", dates);
   }
 
   @Test
@@ -1097,9 +1695,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
     if (!Boolean.getBoolean("enable.update.log")) {
       return;
     }
-    testDatePointFieldsAtomicUpdates("number_p_dt", "date");
-    testDatePointFieldsAtomicUpdates("number_p_dt_dv", "date");
-    testDatePointFieldsAtomicUpdates("number_p_dt_dv_ns", "date");
+    testDatePointFieldsAtomicUpdates("number_p_dt");
+    testDatePointFieldsAtomicUpdates("number_p_dt_dv");
+    testDatePointFieldsAtomicUpdates("number_p_dt_dv_ns");
   }
 
   @Test
@@ -1107,9 +1705,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
     if (!Boolean.getBoolean("enable.update.log")) {
       return;
     }
-    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_mv", "date");
-    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_ni_mv_dv", "date");
-    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_dv_ns_mv", "date");
+    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_mv");
+    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_ni_mv_dv");
+    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_dv_ns_mv");
   }
 
   @Test
@@ -1122,45 +1720,59 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testDatePointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_dt_ni", getSequentialStringArrayWithDates(10));
-    doTestFieldNotIndexed("number_p_dt_ni_mv", getSequentialStringArrayWithDates(10));
+    String[] dates = toStringArray(getRandomInstants(10, false));
+    doTestFieldNotIndexed("number_p_dt_ni", dates);
+    doTestFieldNotIndexed("number_p_dt_ni_mv", dates);
   }
   
   @Test
   public void testIndexOrDocValuesQuery() throws Exception {
-    String[] fieldTypeNames = new String[]{"_p_i", "_p_l", "_p_d", "_p_f"};
-    FieldType[] fieldTypes = new FieldType[]{new IntPointField(), new LongPointField(), new DoublePointField(), new FloatPointField()};
-    assert fieldTypeNames.length == fieldTypes.length;
+    String[] fieldTypeNames = new String[] { "_p_i", "_p_l", "_p_d", "_p_f", "_p_dt" };
+    FieldType[] fieldTypes = new FieldType[]
+        { new IntPointField(), new LongPointField(), new DoublePointField(), new FloatPointField(), new DatePointField() };
+    String[] ints = toStringArray(getRandomInts(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] longs = toStringArray(getRandomLongs(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] doubles = toStringArray(getRandomDoubles(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] floats = toStringArray(getRandomFloats(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] dates = toStringArray(getRandomInstants(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] min = new String[] { ints[0], longs[0], doubles[0], floats[0], dates[0] };
+    String[] max = new String[] { ints[1], longs[1], doubles[1], floats[1], dates[1] };
+    assert fieldTypeNames.length == fieldTypes.length
+        && fieldTypeNames.length == max.length
+        && fieldTypeNames.length == min.length;
     for (int i = 0; i < fieldTypeNames.length; i++) {
       SchemaField fieldIndexed = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i]);
       SchemaField fieldIndexedAndDv = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i] + "_dv");
       SchemaField fieldIndexedMv = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i] + "_mv");
       SchemaField fieldIndexedAndDvMv = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i] + "_mv_dv");
-      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexed, "0", "10", true, true) instanceof PointRangeQuery);
-      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDv, "0", "10", true, true) instanceof IndexOrDocValuesQuery);
-      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedMv, "0", "10", true, true) instanceof PointRangeQuery);
-      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDvMv, "0", "10", true, true) instanceof IndexOrDocValuesQuery);
-      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexed, "0") instanceof PointRangeQuery);
-      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDv, "0") instanceof IndexOrDocValuesQuery);
-      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedMv, "0") instanceof PointRangeQuery);
-      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDvMv, "0") instanceof IndexOrDocValuesQuery);
+      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexed, min[i], max[i], true, true) instanceof PointRangeQuery);
+      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDv, min[i], max[i], true, true) instanceof IndexOrDocValuesQuery);
+      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedMv, min[i], max[i], true, true) instanceof PointRangeQuery);
+      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDvMv, min[i], max[i], true, true) instanceof IndexOrDocValuesQuery);
+      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexed, min[i]) instanceof PointRangeQuery);
+      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDv, min[i]) instanceof IndexOrDocValuesQuery);
+      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedMv, min[i]) instanceof PointRangeQuery);
+      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDvMv, min[i]) instanceof IndexOrDocValuesQuery);
     }
   }
   
   public void testInternals() throws IOException {
-    String[] types = new String[]{"i", "l", "f", "d"};
+    String[] types = new String[]{"i", "l", "f", "d", "dt"};
+    String[][] values = new String[][] {
+        toStringArray(getRandomInts(10, false)),
+        toStringArray(getRandomLongs(10, false)),
+        toStringArray(getRandomFloats(10, false)),
+        toStringArray(getRandomDoubles(10, false)),
+        toStringArray(getRandomInstants(10, false))
+    };
+    assertEquals(types.length, values.length);
     Set<String> typesTested = new HashSet<>();
-    for (String type:types) {
+    for (int i = 0 ; i < types.length ; ++i) {
       for (String suffix:FIELD_SUFFIXES) {
-        doTestInternals("number_p_" + type + suffix, getSequentialStringArrayWithInts(10));
-        typesTested.add("*_p_" + type + suffix);
+        doTestInternals("number_p_" + types[i] + suffix, values[i]);
+        typesTested.add("*_p_" + types[i] + suffix);
       }
     }
-    for (String suffix:FIELD_SUFFIXES) {
-      doTestInternals("number_p_dt" + suffix, getSequentialStringArrayWithDates(10));
-      typesTested.add("*_p_dt" + suffix);
-    }
-
     assertEquals("Missing types in the test", dynFieldRegexesForType(PointField.class), typesTested);
   }
   
@@ -1197,24 +1809,43 @@ public class TestPointFields extends SolrTestCaseJ4 {
   }
 
   private List<Double> getRandomDoubles(int length, boolean missingVals) {
-    return getRandomList(length, missingVals, 
-        () -> random().nextDouble() * Double.MAX_VALUE * (random().nextBoolean() ? 1.D : -1.D));
+    return getRandomList(length, missingVals, () -> {
+      Double d = Double.NaN; 
+      while (d.isNaN()) {
+        d = Double.longBitsToDouble(random().nextLong());
+      }
+      return d; 
+    });
   }
 
   private List<Float> getRandomFloats(int length, boolean missingVals) {
-    return getRandomList(length, missingVals,
-        () -> random().nextFloat() * Float.MAX_VALUE * (random().nextBoolean() ? 1.f : -1.f));
+    return getRandomList(length, missingVals, () -> {
+      Float f = Float.NaN;
+      while (f.isNaN()) {
+        f = Float.intBitsToFloat(random().nextInt());
+      }
+      return f;
+    });
+  }
+
+  private List<Integer> getRandomInts(int length, boolean missingVals, int bound) {
+    return getRandomList(length, missingVals, () -> random().nextInt() % bound);
   }
 
   private List<Integer> getRandomInts(int length, boolean missingVals) {
     return getRandomList(length, missingVals, () -> random().nextInt());
   }
 
-  private List<Long> getRandomLongs(int length, boolean missingVals){
+  private List<Long> getRandomLongs(int length, boolean missingVals, long bound) {
+    assert bound > 0L;
+    return getRandomList(length, missingVals, () -> random().nextLong() % bound); // see Random.nextInt(int bound)
+  }
+
+  private List<Long> getRandomLongs(int length, boolean missingVals) {
     return getRandomList(length, missingVals, () -> random().nextLong());
   }
 
-  private List<Instant> getRandomInstants(int length, boolean missingVals){
+  private List<Instant> getRandomInstants(int length, boolean missingVals) {
     return getRandomList(length, missingVals, () -> Instant.ofEpochMilli(random().nextLong()));
   }
   
@@ -1272,47 +1903,46 @@ public class TestPointFields extends SolrTestCaseJ4 {
     doTestIntPointFieldExactQuery(field, testLong, true);
   }
 
+  private String getTestString(boolean searchable, int numFound) {
+    return "//*[@numFound='" + (searchable ? Integer.toString(numFound) : "0") + "']";
+  }
+  
   /**
    * @param field the field to use for indexing and searching against
    * @param testLong set to true if "field" is expected to support long values, false if only integers
    * @param searchable set to true if searches against "field" should succeed, false if field is only stored and searches should always get numFound=0
    */
   private void doTestIntPointFieldExactQuery(final String field, final boolean testLong, final boolean searchable) throws Exception {
-    final String MATCH_ONE = "//*[@numFound='" + (searchable ? "1" : "0") + "']";
-    final String MATCH_TWO = "//*[@numFound='" + (searchable ? "2" : "0") + "']";
-
-    for (int i=0; i < 10; i++) {
-      assertU(adoc("id", String.valueOf(i), field, String.valueOf(i+1)));
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    Map<String,Integer> randCount = new HashMap<>(numValues);
+    String[] rand = testLong ? toStringArray(getRandomLongs(numValues, false))
+                             : toStringArray(getRandomInts(numValues, false));
+    for (int i = 0 ; i < numValues ; i++) {
+      randCount.merge(rand[i], 1, (a, b) -> a + b); // count unique values
+      assertU(adoc("id", String.valueOf(i), field, rand[i]));
     }
     assertU(commit());
-    for (int i = 0; i < 10; i++) {
-      assertQ(req("q", field + ":"+(i+1), "fl", "id, " + field), 
-          MATCH_ONE);
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertQ(req("q", field + ":" + (rand[i].startsWith("-") ? "\\" : "") + rand[i],
+          "fl", "id," + field), getTestString(searchable, randCount.get(rand[i])));
     }
     
-    for (int i = 0; i < 10; i++) {
-      assertQ(req("debug", "true", "q", field + ":" + (i+1) + " OR " + field + ":" + ((i+1)%10 + 1)), MATCH_TWO);
+    StringBuilder builder = new StringBuilder();
+    for (String value : randCount.keySet()) {
+      if (builder.length() != 0) {
+        builder.append(" OR ");
+      }
+      if (value.startsWith("-")) {
+        builder.append("\\"); // escape negative sign
+      }
+      builder.append(value);
     }
+    assertQ(req("debug", "true", "q", field + ":(" + builder.toString() + ")"), getTestString(searchable, numValues));
     
     assertU(adoc("id", String.valueOf(Integer.MAX_VALUE), field, String.valueOf(Integer.MAX_VALUE)));
     assertU(commit());
-    assertQ(req("q", field + ":"+Integer.MAX_VALUE, "fl", "id, " + field), 
-        MATCH_ONE);
-    
-    if (testLong) {
-      for (long i = (long)Integer.MAX_VALUE; i < (long)Integer.MAX_VALUE + 10; i++) {
-        assertU(adoc("id", String.valueOf(i), field, String.valueOf(i+1)));
-      }
-      assertU(commit());
-      for (long i = (long)Integer.MAX_VALUE; i < (long)Integer.MAX_VALUE + 10; i++) {
-        assertQ(req("q", field + ":"+(i+1), "fl", "id, " + field), 
-                MATCH_ONE);
-      }
-      assertU(adoc("id", String.valueOf(Long.MAX_VALUE), field, String.valueOf(Long.MAX_VALUE)));
-      assertU(commit());
-      assertQ(req("q", field + ":"+Long.MAX_VALUE, "fl", "id, " + field), 
-              MATCH_ONE);
-    }
+    assertQ(req("q", field + ":"+Integer.MAX_VALUE, "fl", "id, " + field), getTestString(searchable, 1));
     
     clearIndex();
     assertU(commit());
@@ -1489,54 +2119,6 @@ public class TestPointFields extends SolrTestCaseJ4 {
         SolrException.ErrorCode.BAD_REQUEST);
   }
   
-  private void doTestIntPointFieldRangeFacet(String docValuesField, String nonDocValuesField) throws Exception {
-    for (int i = 0; i < 10; i++) {
-      assertU(adoc("id", String.valueOf(i), docValuesField, String.valueOf(i), nonDocValuesField, String.valueOf(i)));
-    }
-    assertU(commit());
-    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
-    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
-    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2"), 
-        "//*[@numFound='10']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
-    
-    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "dv"), 
-        "//*[@numFound='10']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
-    
-    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
-    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
-    // Range Faceting with method = filter should work
-    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "filter"), 
-        "//*[@numFound='10']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
-    
-    // this should actually use filter method instead of dv
-    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "dv"), 
-        "//*[@numFound='10']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
-  }
-
   private void doTestIntPointFunctionQuery(String field, String type) throws Exception {
     for (int i = 9; i >= 0; i--) {
       assertU(adoc("id", String.valueOf(i), field, String.valueOf(i)));
@@ -1600,7 +2182,7 @@ public class TestPointFields extends SolrTestCaseJ4 {
   }
 
   
-  private void testPointStats(String field, String dvField, String[] numbers, double min, double max, String count, String missing, double delta) {
+  private void testPointStats(String field, String dvField, String[] numbers, double min, double max, int count, int missing, double delta) {
     String minMin = String.valueOf(min - Math.abs(delta*min));
     String maxMin = String.valueOf(min + Math.abs(delta*min));
     String minMax = String.valueOf(max - Math.abs(delta*max));
@@ -1614,10 +2196,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
     assertTrue(h.getCore().getLatestSchema().getField(dvField).getType() instanceof PointField);
     assertQ(req("q", "*:*", "fl", "id, " + dvField, "stats", "true", "stats.field", dvField), 
         "//*[@numFound='11']",
-        "//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/double[@name='min'][.>='" + minMin + "']",
-        "//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/double[@name='min'][.<='" + maxMin+ "']",
-        "//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/double[@name='max'][.>='" + minMax + "']",
-        "//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dv

<TRUNCATED>

[2/6] lucene-solr:master: SOLR-10796: TestPointFields: increase randomized testing of non-trivial values

Posted by sa...@apache.org.
SOLR-10796: TestPointFields: increase randomized testing of non-trivial values


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/5bb09e08
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/5bb09e08
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/5bb09e08

Branch: refs/heads/master
Commit: 5bb09e08528552c310d30fc627dc823a86aa6880
Parents: 2015359
Author: Steve Rowe <sa...@apache.org>
Authored: Mon Jul 10 19:58:23 2017 -0400
Committer: Steve Rowe <sa...@apache.org>
Committed: Mon Jul 10 19:58:23 2017 -0400

----------------------------------------------------------------------
 solr/CHANGES.txt                                |    2 +
 .../org/apache/solr/schema/TestPointFields.java | 1400 ++++++++++++------
 2 files changed, 938 insertions(+), 464 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb09e08/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index c6100b3..02d2364 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -484,6 +484,8 @@ Other Changes
 
 * SOLR-10898: Fix SOLR-10898 to not deterministicly fail 1/512 runs (hossman)
 
+* SOLR-10796: TestPointFields: increase randomized testing of non-trivial values.  (Steve Rowe)
+
 ==================  6.7.0 ==================
 
 Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release.


[3/6] lucene-solr:branch_7x: SOLR-10796: TestPointFields: increase randomized testing of non-trivial values

Posted by sa...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/83400bd8/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/TestPointFields.java b/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
index a1d2260..3dac18c 100644
--- a/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
+++ b/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
@@ -17,17 +17,24 @@
 package org.apache.solr.schema;
 
 import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
 import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
@@ -69,13 +76,13 @@ import org.junit.Test;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
-/**
- * Tests for PointField functionality
- *
- *
- */
+/** Tests for PointField functionality */
 public class TestPointFields extends SolrTestCaseJ4 {
-  
+
+  // long overflow can occur in some date calculations if gaps are too large, so we limit to a million years BC & AD.
+  private static final long MIN_DATE_EPOCH_MILLIS = LocalDateTime.parse("-1000000-01-01T00:00:00").toInstant(ZoneOffset.ofHours(0)).toEpochMilli();
+  private static final long MAX_DATE_EPOCH_MILLIS = LocalDateTime.parse("+1000000-01-01T00:00:00").toInstant(ZoneOffset.ofHours(0)).toEpochMilli();
+
   private static final String[] FIELD_SUFFIXES = new String[] {
       "", "_dv", "_mv", "_mv_dv", "_ni", "_ni_dv", "_ni_dv_ns", "_ni_dv_ns_mv", 
       "_ni_mv", "_ni_mv_dv", "_ni_ns", "_ni_ns_mv", "_dv_ns", "_ni_ns_dv", "_dv_ns_mv",
@@ -115,9 +122,11 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testIntPointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_i", "int", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99"});
-    testPointFieldReturn("number_p_i_dv_ns", "int", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99"});
-    testPointFieldReturn("number_p_i_ni", "int", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99"});
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] ints = toStringArray(getRandomInts(numValues, false));
+    testPointFieldReturn("number_p_i", "int", ints);
+    testPointFieldReturn("number_p_i_dv_ns", "int", ints);
+    testPointFieldReturn("number_p_i_ni", "int", ints);
   }
   
   @Test
@@ -129,9 +138,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testIntPointFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni", "42");
-    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns", "42");
-    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns_mv", "42", "666");
+    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni", toStringArray(getRandomInts(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns", toStringArray(getRandomInts(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns_mv", toStringArray(getRandomInts(numValues, false)));
   }
   
   @Test
@@ -162,8 +172,8 @@ public class TestPointFields extends SolrTestCaseJ4 {
     for (String r : Arrays.asList("*_p_i_ni", "*_p_i_ni_ns")) {
       assertTrue(r, regexToTest.remove(r));
       String field = r.replace("*", "number");
-      doTestPointFieldSortError(field, "w/o docValues", "42");
-      doTestPointFieldFunctionQueryError(field, "w/o docValues", "42");
+      doTestPointFieldSortError(field, "w/o docValues", toStringArray(getRandomInts(1, false)));
+      doTestPointFieldFunctionQueryError(field, "w/o docValues", toStringArray(getRandomInts(1, false)));
     }
     
     for (String r : Arrays.asList("*_p_i_mv", "*_p_i_ni_mv", "*_p_i_ni_mv_dv", "*_p_i_ni_dv_ns_mv",
@@ -172,10 +182,11 @@ public class TestPointFields extends SolrTestCaseJ4 {
                                   "*_p_i_mv_sml", "*_p_i_mv_dv_sml", "*_p_i_ni_mv_dv_sml")) {
       assertTrue(r, regexToTest.remove(r));
       String field = r.replace("*", "number");
-      doTestPointFieldSortError(field, "multivalued", "42");
-      doTestPointFieldSortError(field, "multivalued", "42", "666");
-      doTestPointFieldFunctionQueryError(field, "multivalued", "42");
-      doTestPointFieldFunctionQueryError(field, "multivalued", "42", "666");
+      doTestPointFieldSortError(field, "multivalued", toStringArray(getRandomInts(1, false)));
+      int numValues = 2 * RANDOM_MULTIPLIER;
+      doTestPointFieldSortError(field, "multivalued", toStringArray(getRandomInts(numValues, false)));
+      doTestPointFieldFunctionQueryError(field, "multivalued", toStringArray(getRandomInts(1, false)));
+      doTestPointFieldFunctionQueryError(field, "multivalued", toStringArray(getRandomInts(numValues, false)));
    }
     
     assertEquals("Missing types in the test", Collections.<String>emptySet(), regexToTest);
@@ -184,68 +195,214 @@ public class TestPointFields extends SolrTestCaseJ4 {
   @Test
   public void testIntPointFieldFacetField() throws Exception {
     testPointFieldFacetField("number_p_i", "number_p_i_dv", getSequentialStringArrayWithInts(10));
+    clearIndex();
+    assertU(commit());
+    testPointFieldFacetField("number_p_i", "number_p_i_dv", toStringArray(getRandomInts(10, false)));
   }
 
   @Test
   public void testIntPointFieldRangeFacet() throws Exception {
-    doTestIntPointFieldRangeFacet("number_p_i_dv", "number_p_i");
+    String docValuesField = "number_p_i_dv";
+    String nonDocValuesField = "number_p_i";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Integer> values;
+    List<Integer> sortedValues;
+    int max;
+    do {
+      values = getRandomInts(numValues, false);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+    } while ((max = sortedValues.get(sortedValues.size() - 1)) >= Integer.MAX_VALUE - numValues); // leave room for rounding 
+    int min = sortedValues.get(0);
+    int gap = (int)(((long)(max + numValues) - (long)min) / (long)numBuckets);
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    int minBucketVal = min;
+    for (Integer value : sortedValues) {
+      while (((long)value - (long)minBucketVal) >= (long)gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i), docValuesField, String.valueOf(values.get(i)), nonDocValuesField, String.valueOf(values.get(i))));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap)),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
   }
 
   @Test
   public void testIntPointStats() throws Exception {
-    testPointStats("number_p_i", "number_p_i_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
-        0D, 9D, "10", "1", 0D);
-    testPointStats("number_p_i", "number_p_i_mv_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
-        0D, 9D, "10", "1", 0D);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    // don't produce numbers with exponents, since XPath comparison operators can't handle them
+    List<Integer> values  = getRandomInts(numValues, false, 9999999);
+    System.err.println(Arrays.toString(values.toArray(new Integer[values.size()])));
+    List<Integer> sortedValues = values.stream().sorted().collect(Collectors.toList());
+    double min = (double)sortedValues.get(0);
+    double max = (double)sortedValues.get(sortedValues.size() - 1);
+
+    String[] valArray = toStringArray(values);
+    testPointStats("number_p_i", "number_p_i_dv", valArray, min, max, numValues, 1, 0D);
+    testPointStats("number_p_i", "number_p_i_mv_dv", valArray, min, max, numValues, 1, 0D);
   }
 
   @Test
   public void testIntPointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_i_mv", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedExactQuery("number_p_i_ni_mv_dv", getSequentialStringArrayWithInts(20));
+    String[] ints = toStringArray(getRandomInts(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_i_mv", ints);
+    testPointFieldMultiValuedExactQuery("number_p_i_ni_mv_dv", ints);
   }
 
   @Test
   public void testIntPointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_i_ni_mv", getSequentialStringArrayWithInts(20), false);
-    testPointFieldMultiValuedExactQuery("number_p_i_ni_ns_mv", getSequentialStringArrayWithInts(20), false);
+    String[] ints = toStringArray(getRandomInts(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_i_ni_mv", ints, false);
+    testPointFieldMultiValuedExactQuery("number_p_i_ni_ns_mv", ints, false);
   }
   
   @Test
   public void testIntPointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_i_mv", "int", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedReturn("number_p_i_ni_mv_dv", "int", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedReturn("number_p_i_dv_ns_mv", "int", getSequentialStringArrayWithInts(20));
+    String[] ints = toStringArray(getRandomInts(20, false));
+    testPointFieldMultiValuedReturn("number_p_i_mv", "int", ints);
+    testPointFieldMultiValuedReturn("number_p_i_ni_mv_dv", "int", ints);
+    testPointFieldMultiValuedReturn("number_p_i_dv_ns_mv", "int", ints);
   }
   
   @Test
   public void testIntPointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_i_mv", "int", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedRangeQuery("number_p_i_ni_mv_dv", "int", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedRangeQuery("number_p_i_mv_dv", "int", getSequentialStringArrayWithInts(20));
+    String[] ints = toStringArray(getRandomInts(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_i_mv", "int", ints);
+    testPointFieldMultiValuedRangeQuery("number_p_i_ni_mv_dv", "int", ints);
+    testPointFieldMultiValuedRangeQuery("number_p_i_mv_dv", "int", ints);
   }
   
   @Test
   public void testIntPointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_i_ni", getSequentialStringArrayWithInts(10));
-    doTestFieldNotIndexed("number_p_i_ni_mv", getSequentialStringArrayWithInts(10));
+    String[] ints = toStringArray(getRandomInts(10, false));
+    doTestFieldNotIndexed("number_p_i_ni", ints);
+    doTestFieldNotIndexed("number_p_i_ni_mv", ints);
   }
   
   //TODO MV SORT?
   @Test
   public void testIntPointFieldMultiValuedFacetField() throws Exception {
     testPointFieldMultiValuedFacetField("number_p_i_mv", "number_p_i_mv_dv", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedFacetField("number_p_i_mv", "number_p_i_mv_dv", toStringArray(getRandomInts(20, false)));
+    String[] randomSortedInts = toStringArray(getRandomInts(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedFacetField("number_p_i_mv", "number_p_i_mv_dv", randomSortedInts);
   }
 
   @Test
   public void testIntPointFieldMultiValuedRangeFacet() throws Exception {
-    doTestIntPointFieldMultiValuedRangeFacet("number_p_i_mv_dv", "number_p_i_mv");
+    String docValuesField = "number_p_i_mv_dv";
+    String nonDocValuesField = "number_p_i_mv";
+    int numValues = 20 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Integer> values;
+    List<PosVal<Integer>> sortedValues;
+    int max;
+    do {
+      values = getRandomInts(numValues, false);
+      sortedValues = toAscendingPosVals(values, true);
+    } while ((max = sortedValues.get(sortedValues.size() - 1).val) >= Integer.MAX_VALUE - numValues); // leave room for rounding
+    int min = sortedValues.get(0).val;
+    int gap = (int)(((long)(max + numValues) - (long)min) / (long)numBuckets);
+    List<Set<Integer>> docIdBucket = new ArrayList<>(numBuckets);
+    for (int i = 0 ; i < numBuckets ; ++i) {
+      docIdBucket.add(new HashSet<>());
+    }
+    int bucketNum = 0;
+    int minBucketVal = min;
+    for (PosVal<Integer> value : sortedValues) {
+      while (value.val - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+      }
+      docIdBucket.get(bucketNum).add(value.pos / 2); // each doc gets two consecutive values 
+    }
+    for (int i = 0 ; i < numValues ; i += 2) {
+      assertU(adoc("id", String.valueOf(i / 2),
+          docValuesField, String.valueOf(values.get(i)),
+          docValuesField, String.valueOf(values.get(i + 1)),
+          nonDocValuesField, String.valueOf(values.get(i)),
+          nonDocValuesField, String.valueOf(values.get(i + 1))));
+    }
+    assertU(commit());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    minBucketVal = min;
+    testStrings[numBuckets] = "//*[@numFound='" + (numValues / 2) + "']";
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + docIdBucket.get(i).size() + "']";
+    }
+
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "indent", "on"),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv", "indent", "on"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + docIdBucket.get(i).size() + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter", "indent", "on"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv", "indent", "on"),
+        testStrings);
   }
 
   @Test
-  public void testIntPointMultiValuedFunctionQuery() throws Exception {
+  public void testIntPointMultiValuedFunctionQuery() throws Exception {       
     testPointMultiValuedFunctionQuery("number_p_i_mv", "number_p_i_mv_dv", "int", getSequentialStringArrayWithInts(20));
+    testPointMultiValuedFunctionQuery("number_p_i_mv", "number_p_i_mv_dv", "int",
+        toStringArray(getRandomInts(20, false).stream().sorted().collect(Collectors.toList())));
   }
   
   @Test
@@ -280,6 +437,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
       this.pos = pos;
       this.val = val;
     }
+    public String toString() {
+      return "(" + pos + ": " + val.toString() + ")";
+    }
   }
 
   /** Primary sort by value, with nulls either first or last as specified, and then secondary sort by position. */
@@ -345,33 +505,29 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDoublePointFieldExactQuery() throws Exception {
-    doTestFloatPointFieldExactQuery("number_d");
-    doTestFloatPointFieldExactQuery("number_p_d");
-    doTestFloatPointFieldExactQuery("number_p_d_mv");
-    doTestFloatPointFieldExactQuery("number_p_d_dv");
-    doTestFloatPointFieldExactQuery("number_p_d_mv_dv");
-    doTestFloatPointFieldExactQuery("number_p_d_ni_dv");
-    doTestFloatPointFieldExactQuery("number_p_d_ni_ns_dv");
-    doTestFloatPointFieldExactQuery("number_p_d_ni_dv_ns");
-    doTestFloatPointFieldExactQuery("number_p_d_ni_mv_dv");
+    doTestFloatPointFieldExactQuery("number_d", true);
+    doTestFloatPointFieldExactQuery("number_p_d", true);
+    doTestFloatPointFieldExactQuery("number_p_d_mv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_dv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_mv_dv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_dv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_ns_dv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_dv_ns", true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_mv_dv", true);
   }
   
   @Test
   public void testDoublePointFieldNonSearchableExactQuery() throws Exception {
-    doTestFloatPointFieldExactQuery("number_p_d_ni", false);
-    doTestFloatPointFieldExactQuery("number_p_d_ni_ns", false);
+    doTestFloatPointFieldExactQuery("number_p_d_ni", false, true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_ns", false, true);
   }
  
   @Test
   public void testDoublePointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_d", "double", new String[]{"0.0", "1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
-    testPointFieldReturn("number_p_d_dv_ns", "double", new String[]{"0.0", "1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
-    String[] arr = new String[atLeast(10)];
-    for (int i = 0; i < arr.length; i++) {
-      double rand = random().nextDouble() * 10;
-      arr[i] = String.valueOf(rand);
-    }
-    testPointFieldReturn("number_p_d", "double", arr);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] doubles = toStringArray(getRandomDoubles(numValues, false));
+    testPointFieldReturn("number_p_d", "double", doubles);
+    testPointFieldReturn("number_p_d_dv_ns", "double", doubles);
   }
   
   @Test
@@ -383,9 +539,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testDoubleFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni", "42.3");
-    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns", "42.3");
-    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns_mv", "42.3", "-66.6");
+    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni", toStringArray(getRandomDoubles(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns", toStringArray(getRandomDoubles(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns_mv", toStringArray(getRandomDoubles(numValues, false)));
   }
   
   
@@ -446,41 +603,121 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDoublePointFieldRangeFacet() throws Exception {
-    doTestFloatPointFieldRangeFacet("number_p_d_dv", "number_p_d");
+    String docValuesField = "number_p_d_dv";
+    String nonDocValuesField = "number_p_d";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Double> values, sortedValues;
+    double min, max, gap, buffer;
+    do {
+      values = getRandomDoubles(numValues, false);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+      min = sortedValues.get(0);
+      max = sortedValues.get(sortedValues.size() - 1);
+      buffer = BigDecimal.valueOf(max).subtract(BigDecimal.valueOf(min))
+          .divide(BigDecimal.valueOf(numValues), RoundingMode.HALF_UP)
+          .divide(BigDecimal.valueOf(2.0D), RoundingMode.HALF_UP).doubleValue();
+      gap = BigDecimal.valueOf(max + buffer).subtract(BigDecimal.valueOf(min - buffer))
+          .divide(BigDecimal.valueOf(numBuckets), RoundingMode.HALF_UP).doubleValue();
+    } while (max >= Double.MAX_VALUE - buffer || min <= -Double.MAX_VALUE + buffer);
+    // System.err.println("min: " + min + "   max: " + max + "   gap: " + gap + "   buffer: " + buffer);
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    double minBucketVal = min - buffer;
+    // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + minBucketVal);
+    for (double value : sortedValues) {
+      // System.err.println("value: " + value);
+      while (value - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+        // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + minBucketVal);
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i),
+          docValuesField, String.valueOf(values.get(i)), nonDocValuesField, String.valueOf(values.get(i))));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min - buffer;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap)),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min - buffer;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
   }
 
   @Test
   public void testDoublePointStats() throws Exception {
-    testPointStats("number_p_d", "number_p_d_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-        -10.0D, 9.9D, "10", "1", 1E-10D);
-    testPointStats("number_p_d_mv", "number_p_d_mv_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-        -10.0D, 9.9D, "10", "1", 1E-10D);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    // don't produce numbers with exponents, since XPath comparison operators can't handle them: 7 digits of precision
+    List<Float> values  = getRandomInts(numValues, false, 9999999).stream()
+        .map(v -> (float)((double)v * Math.pow(10D, -1 * random().nextInt(8)))).collect(Collectors.toList());
+    System.err.println(Arrays.toString(values.toArray(new Float[values.size()])));
+    List<Float> sortedValues = values.stream().sorted().collect(Collectors.toList());
+    double min = (double)sortedValues.get(0);
+    double max = (double)sortedValues.get(sortedValues.size() - 1);
+
+    String[] valArray = toStringArray(values);
+    testPointStats("number_p_d", "number_p_d_dv", valArray, min, max, numValues, 1, 1E-7D);
+    testPointStats("number_p_d", "number_p_d_mv_dv", valArray, min, max, numValues, 1, 1E-7D);
   }
   
   @Test
   public void testDoublePointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_d_mv", toStringArray(getRandomDoubles(20, false)));
-    testPointFieldMultiValuedExactQuery("number_p_d_ni_mv_dv", toStringArray(getRandomDoubles(20, false)));
+    String[] doubles = toStringArray(getRandomDoubles(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_d_mv", doubles);
+    testPointFieldMultiValuedExactQuery("number_p_d_ni_mv_dv", doubles);
   }
   
   @Test
   public void testDoublePointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_d_ni_mv", toStringArray(getRandomDoubles(20, false)), false);
-    testPointFieldMultiValuedExactQuery("number_p_d_ni_ns_mv", toStringArray(getRandomDoubles(20, false)), false);
+    String[] doubles = toStringArray(getRandomDoubles(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_d_ni_mv", doubles, false);
+    testPointFieldMultiValuedExactQuery("number_p_d_ni_ns_mv", doubles, false);
   }
   
   @Test
   public void testDoublePointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_d_mv", "double", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedReturn("number_p_d_ni_mv_dv", "double", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedReturn("number_p_d_dv_ns_mv", "double", getSequentialStringArrayWithDoubles(20));
+    String[] doubles = toStringArray(getRandomDoubles(20, false));
+    testPointFieldMultiValuedReturn("number_p_d_mv", "double", doubles);
+    testPointFieldMultiValuedReturn("number_p_d_ni_mv_dv", "double", doubles);
+    testPointFieldMultiValuedReturn("number_p_d_dv_ns_mv", "double", doubles);
   }
   
   @Test
   public void testDoublePointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_d_mv", "double", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedRangeQuery("number_p_d_ni_mv_dv", "double", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedRangeQuery("number_p_d_mv_dv", "double", getSequentialStringArrayWithDoubles(20));
+    String[] doubles = toStringArray(getRandomDoubles(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_d_mv", "double", doubles);
+    testPointFieldMultiValuedRangeQuery("number_p_d_ni_mv_dv", "double", doubles);
+    testPointFieldMultiValuedRangeQuery("number_p_d_mv_dv", "double", doubles);
   }
   
   @Test
@@ -522,8 +759,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testDoublePointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_d_ni", getSequentialStringArrayWithDoubles(10));
-    doTestFieldNotIndexed("number_p_d_ni_mv", getSequentialStringArrayWithDoubles(10));
+    String[] doubles = toStringArray(getRandomDoubles(10, false));
+    doTestFieldNotIndexed("number_p_d_ni", doubles);
+    doTestFieldNotIndexed("number_p_d_ni_mv", doubles);
   }
   
   
@@ -571,32 +809,28 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testFloatPointFieldExactQuery() throws Exception {
-    doTestFloatPointFieldExactQuery("number_p_f");
-    doTestFloatPointFieldExactQuery("number_p_f_mv");
-    doTestFloatPointFieldExactQuery("number_p_f_dv");
-    doTestFloatPointFieldExactQuery("number_p_f_mv_dv");
-    doTestFloatPointFieldExactQuery("number_p_f_ni_dv");
-    doTestFloatPointFieldExactQuery("number_p_f_ni_ns_dv");
-    doTestFloatPointFieldExactQuery("number_p_f_ni_dv_ns");
-    doTestFloatPointFieldExactQuery("number_p_f_ni_mv_dv");
+    doTestFloatPointFieldExactQuery("number_p_f", false);
+    doTestFloatPointFieldExactQuery("number_p_f_mv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_dv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_mv_dv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_dv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_ns_dv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_dv_ns", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_mv_dv", false);
   }
   
   @Test
   public void testFloatPointFieldNonSearchableExactQuery() throws Exception {
-    doTestFloatPointFieldExactQuery("number_p_f_ni", false);
-    doTestFloatPointFieldExactQuery("number_p_f_ni_ns", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni", false, false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_ns", false, false);
   }
   
   @Test
   public void testFloatPointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_f", "float", new String[]{"0.0", "-1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
-    testPointFieldReturn("number_p_f_dv_ns", "float", new String[]{"0.0", "-1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
-    String[] arr = new String[atLeast(10)];
-    for (int i = 0; i < arr.length; i++) {
-      float rand = random().nextFloat() * 10;
-      arr[i] = String.valueOf(rand);
-    }
-    testPointFieldReturn("number_p_f", "float", arr);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] floats = toStringArray(getRandomFloats(numValues, false));
+    testPointFieldReturn("number_p_f", "float", floats);
+    testPointFieldReturn("number_p_f_dv_ns", "float", floats);
   }
   
   @Test
@@ -608,9 +842,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testFloatPointFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni", "42.3");
-    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns", "42.3");
-    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns_mv", "42.3", "-66.6");
+    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni", toStringArray(getRandomFloats(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns", toStringArray(getRandomFloats(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns_mv", toStringArray(getRandomFloats(numValues, false)));
   }
   
   @Test
@@ -669,42 +904,120 @@ public class TestPointFields extends SolrTestCaseJ4 {
   }
 
   @Test
+  @AwaitsFix(bugUrl = "https://issues.apache.org/jira/browse/SOLR-11043")
   public void testFloatPointFieldRangeFacet() throws Exception {
-    doTestFloatPointFieldRangeFacet("number_p_f_dv", "number_p_f");
+    String docValuesField = "number_p_f_dv";
+    String nonDocValuesField = "number_p_f";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Float> values, sortedValues;
+    float min, max, gap, buffer;
+    do {
+      values = getRandomFloats(numValues, false);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+      min = sortedValues.get(0);
+      max = sortedValues.get(sortedValues.size() - 1);
+      buffer = (float)(((double)max - (double)min) / (double)numValues / 2.0D);
+      gap = (float)(((double)max + (double)buffer - (double)min + (double)buffer) / (double)numBuckets);
+    } while (max >= Float.MAX_VALUE - buffer || min <= -Float.MAX_VALUE + buffer); 
+    // System.err.println("min: " + min + "   max: " + max + "   gap: " + gap + "   buffer: " + buffer);
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    float minBucketVal = min - buffer;
+    // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + minBucketVal);
+    for (float value : sortedValues) {
+      // System.err.println("value: " + value);
+      while (value - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+        // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + minBucketVal);
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i), 
+          docValuesField, String.valueOf(values.get(i)), nonDocValuesField, String.valueOf(values.get(i))));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min - buffer;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap)),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min - buffer;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
   }
 
   @Test
   public void testFloatPointStats() throws Exception {
-    testPointStats("number_p_f", "number_p_f_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-        -10D, 9.9D, "10", "1", 1E-6D);
-    testPointStats("number_p_f_mv", "number_p_f_mv_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-        -10D, 9.9D, "10", "1", 1E-6D);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    // don't produce numbers with exponents, since XPath comparison operators can't handle them: 7 digits of precision
+    List<Float> values  = getRandomInts(numValues, false, 9999999).stream()
+        .map(v -> (float)((double)v * Math.pow(10D, -1 * random().nextInt(8)))).collect(Collectors.toList());
+    System.err.println(Arrays.toString(values.toArray(new Float[values.size()])));
+    List<Float> sortedValues = values.stream().sorted().collect(Collectors.toList());
+    double min = (double)sortedValues.get(0);
+    double max = (double)sortedValues.get(sortedValues.size() - 1);
+
+    String[] valArray = toStringArray(values);
+    testPointStats("number_p_f", "number_p_f_dv", valArray, min, max, numValues, 1, 1E-7D);
+    testPointStats("number_p_f", "number_p_f_mv_dv", valArray, min, max, numValues, 1, 1E-7D);
   }
   
   @Test
   public void testFloatPointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_f_mv", toStringArray(getRandomFloats(20, false)));
-    testPointFieldMultiValuedExactQuery("number_p_f_ni_mv_dv", toStringArray(getRandomFloats(20, false)));
+    String[] floats = toStringArray(getRandomFloats(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_f_mv", floats);
+    testPointFieldMultiValuedExactQuery("number_p_f_ni_mv_dv", floats);
   }
   
   @Test
   public void testFloatPointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_f_ni_mv", toStringArray(getRandomFloats(20, false)), false);
-    testPointFieldMultiValuedExactQuery("number_p_f_ni_ns_mv", toStringArray(getRandomFloats(20, false)), false);
+    String[] floats = toStringArray(getRandomFloats(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_f_ni_mv", floats, false);
+    testPointFieldMultiValuedExactQuery("number_p_f_ni_ns_mv", floats, false);
   }
   
   @Test
   public void testFloatPointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_f_mv", "float", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedReturn("number_p_f_ni_mv_dv", "float", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedReturn("number_p_f_dv_ns_mv", "float", getSequentialStringArrayWithDoubles(20));
+    String[] floats = toStringArray(getRandomFloats(20, false));
+    testPointFieldMultiValuedReturn("number_p_f_mv", "float", floats);
+    testPointFieldMultiValuedReturn("number_p_f_ni_mv_dv", "float", floats);
+    testPointFieldMultiValuedReturn("number_p_f_dv_ns_mv", "float", floats);
   }
   
   @Test
   public void testFloatPointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_f_mv", "float", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedRangeQuery("number_p_f_ni_mv_dv", "float", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedRangeQuery("number_p_f_mv_dv", "float", getSequentialStringArrayWithDoubles(20));
+    String[] floats = toStringArray(getRandomFloats(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_f_mv", "float", floats);
+    testPointFieldMultiValuedRangeQuery("number_p_f_ni_mv_dv", "float", floats);
+    testPointFieldMultiValuedRangeQuery("number_p_f_mv_dv", "float", floats);
   }
   
   @Test
@@ -754,8 +1067,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testFloatPointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_f_ni", getSequentialStringArrayWithDoubles(10));
-    doTestFieldNotIndexed("number_p_f_ni_mv", getSequentialStringArrayWithDoubles(10));
+    String[] floats = toStringArray(getRandomFloats(10, false));
+    doTestFieldNotIndexed("number_p_f_ni", floats);
+    doTestFieldNotIndexed("number_p_f_ni_mv", floats);
   }
   
   // Long
@@ -780,8 +1094,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_l", "long", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99", String.valueOf(Long.MAX_VALUE)});
-    testPointFieldReturn("number_p_l_dv_ns", "long", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99", String.valueOf(Long.MAX_VALUE)});
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] longs = toStringArray(getRandomLongs(numValues, false));
+    testPointFieldReturn("number_p_l", "long", longs);
+    testPointFieldReturn("number_p_l_dv_ns", "long", longs);
   }
   
   @Test
@@ -793,9 +1109,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni", "3333333333");
-    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns", "3333333333");
-    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns_mv", "3333333333", "-4444444444");
+    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni", toStringArray(getRandomLongs(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns", toStringArray(getRandomLongs(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns_mv", toStringArray(getRandomLongs(numValues, false)));
   }
 
   @Test
@@ -828,8 +1145,8 @@ public class TestPointFields extends SolrTestCaseJ4 {
     for (String r : Arrays.asList("*_p_l_ni", "*_p_l_ni_ns")) {
       assertTrue(r, regexToTest.remove(r));
       String field = r.replace("*", "number");
-      doTestPointFieldSortError(field, "w/o docValues", "4234");
-      doTestPointFieldFunctionQueryError(field, "w/o docValues", "4234");
+      doTestPointFieldSortError(field, "w/o docValues", toStringArray(getRandomLongs(1, false)));
+      doTestPointFieldFunctionQueryError(field, "w/o docValues", toStringArray(getRandomLongs(1, false)));
     }
     
     for (String r : Arrays.asList("*_p_l_mv", "*_p_l_ni_mv", "*_p_l_ni_mv_dv", "*_p_l_ni_dv_ns_mv",
@@ -838,10 +1155,11 @@ public class TestPointFields extends SolrTestCaseJ4 {
                                   "*_p_l_mv_sml", "*_p_l_mv_dv_sml", "*_p_l_ni_mv_dv_sml")) {
       assertTrue(r, regexToTest.remove(r));
       String field = r.replace("*", "number");
-      doTestPointFieldSortError(field, "multivalued", "4234");
-      doTestPointFieldSortError(field, "multivalued", "4234", "66666666");
-      doTestPointFieldFunctionQueryError(field, "multivalued", "4234");
-      doTestPointFieldFunctionQueryError(field, "multivalued", "4234", "66666666");
+      doTestPointFieldSortError(field, "multivalued", toStringArray(getRandomLongs(1, false)));
+      int numValues = 2 * RANDOM_MULTIPLIER;
+      doTestPointFieldSortError(field, "multivalued", toStringArray(getRandomLongs(numValues, false)));
+      doTestPointFieldFunctionQueryError(field, "multivalued", toStringArray(getRandomLongs(1, false)));
+      doTestPointFieldFunctionQueryError(field, "multivalued", toStringArray(getRandomLongs(numValues, false)));
     }
     
     assertEquals("Missing types in the test", Collections.<String>emptySet(), regexToTest);
@@ -857,41 +1175,111 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldRangeFacet() throws Exception {
-    doTestIntPointFieldRangeFacet("number_p_l_dv", "number_p_l");
+    String docValuesField = "number_p_l_dv";
+    String nonDocValuesField = "number_p_l";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Long> values;
+    List<Long> sortedValues;
+    long max;
+    do {
+      values = getRandomLongs(numValues, false);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+    } while ((max = sortedValues.get(sortedValues.size() - 1)) >= Integer.MAX_VALUE - numValues); // leave room for rounding 
+    long min = sortedValues.get(0);
+    long gap = BigInteger.valueOf(max + numValues).subtract(BigInteger.valueOf(min))
+        .divide(BigInteger.valueOf(numBuckets)).longValueExact();
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    long minBucketVal = min;
+    for (Long value : sortedValues) {
+      while (value - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i), docValuesField, String.valueOf(values.get(i)), nonDocValuesField, String.valueOf(values.get(i))));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap)),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
   }
   
   @Test
   public void testLongPointStats() throws Exception {
-    testPointStats("number_p_l", "number_p_l_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
-        0D, 9D, "10", "1", 0D);
-    testPointStats("number_p_l_mv", "number_p_l_mv_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
-        0D, 9D, "10", "1", 0D);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    // don't produce numbers with exponents, since XPath comparison operators can't handle them
+    List<Long> values  = getRandomLongs(numValues, false, 9999999L);
+    List<Long> sortedValues = values.stream().sorted().collect(Collectors.toList());
+    double min = (double)sortedValues.get(0);
+    double max = (double)sortedValues.get(sortedValues.size() - 1);
+
+    String[] valArray = toStringArray(values);
+    testPointStats("number_p_l", "number_p_l_dv", valArray, min, max, numValues, 1, 0D);
+    testPointStats("number_p_l", "number_p_l_mv_dv", valArray, min, max, numValues, 1, 0D);
   }
   
   @Test
   public void testLongPointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_l_mv", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedExactQuery("number_p_l_ni_mv_dv", getSequentialStringArrayWithInts(20));
+    String[] ints = toStringArray(getRandomInts(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_l_mv", ints);
+    testPointFieldMultiValuedExactQuery("number_p_l_ni_mv_dv", ints);
   }
   
   @Test
   public void testLongPointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_l_ni_mv", getSequentialStringArrayWithInts(20), false);
-    testPointFieldMultiValuedExactQuery("number_p_l_ni_ns_mv", getSequentialStringArrayWithInts(20), false);
+    String[] longs = toStringArray(getRandomLongs(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_l_ni_mv", longs, false);
+    testPointFieldMultiValuedExactQuery("number_p_l_ni_ns_mv", longs, false);
   }
   
   @Test
   public void testLongPointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_l_mv", "long", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedReturn("number_p_l_ni_mv_dv", "long", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedReturn("number_p_l_dv_ns_mv", "long", getSequentialStringArrayWithInts(20));
+    String[] longs = toStringArray(getRandomLongs(20, false));
+    testPointFieldMultiValuedReturn("number_p_l_mv", "long", longs);
+    testPointFieldMultiValuedReturn("number_p_l_ni_mv_dv", "long", longs);
+    testPointFieldMultiValuedReturn("number_p_l_dv_ns_mv", "long", longs);
   }
   
   @Test
   public void testLongPointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_l_mv", "long", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedRangeQuery("number_p_l_ni_mv_dv", "long", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedRangeQuery("number_p_l_mv_dv", "long", getSequentialStringArrayWithInts(20));
+    String[] longs = toStringArray(getRandomLongs(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_l_mv", "long", longs);
+    testPointFieldMultiValuedRangeQuery("number_p_l_ni_mv_dv", "long", longs);
+    testPointFieldMultiValuedRangeQuery("number_p_l_mv_dv", "long", longs);
   }
   
   @Test
@@ -902,7 +1290,77 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldMultiValuedRangeFacet() throws Exception {
-    doTestIntPointFieldMultiValuedRangeFacet("number_p_l_mv_dv", "number_p_l_mv");
+    String docValuesField = "number_p_l_mv_dv";
+    String nonDocValuesField = "number_p_l_mv";
+    int numValues = 20 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Long> values;
+    List<PosVal<Long>> sortedValues;
+    long max;
+    do {
+      values = getRandomLongs(numValues, false);
+      sortedValues = toAscendingPosVals(values, true);
+    } while ((max = sortedValues.get(sortedValues.size() - 1).val) >= Long.MAX_VALUE - numValues); // leave room for rounding 
+    long min = sortedValues.get(0).val;
+    long gap = BigInteger.valueOf(max + numValues).subtract(BigInteger.valueOf(min))
+        .divide(BigInteger.valueOf(numBuckets)).longValueExact();
+    List<Set<Integer>> docIdBucket = new ArrayList<>(numBuckets);
+    for (int i = 0 ; i < numBuckets ; ++i) {
+      docIdBucket.add(new HashSet<>());
+    }
+    int bucketNum = 0;
+    long minBucketVal = min;
+    for (PosVal<Long> value : sortedValues) {
+      while (value.val - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+      }
+      docIdBucket.get(bucketNum).add(value.pos / 2); // each doc gets two consecutive values 
+    }
+    for (int i = 0 ; i < numValues ; i += 2) {
+      assertU(adoc("id", String.valueOf(i / 2),
+          docValuesField, String.valueOf(values.get(i)),
+          docValuesField, String.valueOf(values.get(i + 1)),
+          nonDocValuesField, String.valueOf(values.get(i)),
+          nonDocValuesField, String.valueOf(values.get(i + 1))));
+    }
+    assertU(commit());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + (numValues / 2) + "']";
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + docIdBucket.get(i).size() + "']";
+    }
+
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "indent", "on"),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv", "indent", "on"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + docIdBucket.get(i).size() + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter", "indent", "on"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv", "indent", "on"),
+        testStrings);
   }
   
   @Test
@@ -939,8 +1397,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_l_ni", getSequentialStringArrayWithInts(10));
-    doTestFieldNotIndexed("number_p_l_ni_mv", getSequentialStringArrayWithInts(10));
+    String[] longs = toStringArray(getRandomLongs(10, false));
+    doTestFieldNotIndexed("number_p_l_ni", longs);
+    doTestFieldNotIndexed("number_p_l_ni_mv", longs);
   }
 
   // Date
@@ -964,12 +1423,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDatePointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_dt", "date",
-        new String[]{"1995-12-31T23:59:59Z", "1994-02-28T23:59:59Z",
-            "2015-12-31T23:59:59Z", "2000-10-31T23:59:59Z", "1999-12-31T12:59:59Z"});
-    testPointFieldReturn("number_p_dt_dv_ns", "date",
-        new String[]{"1995-12-31T23:59:59Z", "1994-02-28T23:59:59Z",
-            "2015-12-31T23:59:59Z", "2000-10-31T23:59:59Z", "1999-12-31T12:59:59Z"});
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] dates = toStringArray(getRandomInstants(numValues, false));
+    testPointFieldReturn("number_p_dt", "date", dates);
+    testPointFieldReturn("number_p_dt_dv_ns", "date", dates);
   }
 
   @Test
@@ -980,9 +1437,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testDatePointFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni", "1995-12-31T23:59:59Z");
-    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns", "1995-12-31T23:59:59Z");
-    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns_mv", "1995-12-31T23:59:59Z", "2000-10-31T23:59:59Z");
+    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni", toStringArray(getRandomInstants(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns", toStringArray(getRandomInstants(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns_mv", toStringArray(getRandomInstants(numValues, false)));
   }
 
   @Test
@@ -1037,12 +1495,147 @@ public class TestPointFields extends SolrTestCaseJ4 {
     testPointFieldFacetField("number_p_dt", "number_p_dt_dv", getSequentialStringArrayWithDates(10));
     clearIndex();
     assertU(commit());
-    testPointFieldFacetField("number_p_dt", "number_p_dt_dv", getSequentialStringArrayWithDates(10));
-  }
+    testPointFieldFacetField("number_p_dt", "number_p_dt_dv", toStringArray(getRandomInstants(10, false)));
+  }
+
+  private static class DateGapCeiling {
+    String calendarUnit = "MILLIS";
+    long inCalendarUnits;
+    boolean negative = false;
+  
+    /** Maximize calendar unit size given initialGapMillis; performs ceiling on each conversion */
+    DateGapCeiling(long initialGapMillis) {
+      negative = initialGapMillis < 0;
+      inCalendarUnits = Math.abs(initialGapMillis);
+      if (inCalendarUnits >= 1000L) {
+        calendarUnit = "SECS";
+        inCalendarUnits = (inCalendarUnits + 999L) / 1000L;
+        if (inCalendarUnits >= 60L) {
+          calendarUnit = "MINUTES";
+          inCalendarUnits = (inCalendarUnits + 59L) / 60L;
+          if (inCalendarUnits >= 60L) {
+            calendarUnit = "HOURS";
+            inCalendarUnits = (inCalendarUnits + 59L) / 60L;
+            if (inCalendarUnits >= 24L) {
+              calendarUnit = "DAYS";
+              inCalendarUnits = (inCalendarUnits + 23L) / 24L;
+              if (inCalendarUnits >= 12L) {
+                calendarUnit = "MONTHS";
+                inCalendarUnits = (inCalendarUnits + 11L) / 12L;
+                if ((inCalendarUnits * 16) >= 487) {  // 487 = 365.25 / 12 * 16   (365.25 days/year, -ish)
+                  calendarUnit = "YEARS";
+                  inCalendarUnits = (16L * inCalendarUnits + 486) / 487L; 
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    @Override
+    public String toString() {
+      return (negative ? "-" : "+") + inCalendarUnits + calendarUnit;
+    }
 
+    public long addTo(long millis) {  // Instant.plus() doesn't work with estimated durations (MONTHS and YEARS)
+      LocalDateTime time = LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneOffset.ofHours(0));
+      if (negative) {
+        time = time.minus(inCalendarUnits, DateMathParser.CALENDAR_UNITS.get(calendarUnit));
+      } else {
+        time = time.plus(inCalendarUnits, DateMathParser.CALENDAR_UNITS.get(calendarUnit));
+      }
+      return time.atZone(ZoneOffset.ofHours(0)).toInstant().toEpochMilli();
+    }
+  }
+  
   @Test
   public void testDatePointFieldRangeFacet() throws Exception {
-    doTestDatePointFieldRangeFacet("number_p_dt_dv", "number_p_dt");
+    String docValuesField = "number_p_dt_dv";
+    String nonDocValuesField = "number_p_dt";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Long> values, sortedValues;
+    long min, max;
+    DateGapCeiling gap;
+    do {
+      values = getRandomLongs(numValues, false, MAX_DATE_EPOCH_MILLIS);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+      min = sortedValues.get(0);
+      max = sortedValues.get(sortedValues.size() - 1);
+    } while (max > MAX_DATE_EPOCH_MILLIS || min <= MIN_DATE_EPOCH_MILLIS);
+    long initialGap = BigInteger.valueOf(max).subtract(BigInteger.valueOf(min))
+        .divide(BigInteger.valueOf(numBuckets)).longValueExact();
+    gap = new DateGapCeiling(BigInteger.valueOf(max + initialGap).subtract(BigInteger.valueOf(min)) // padding for rounding
+        .divide(BigInteger.valueOf(numBuckets)).longValueExact());
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    long minBucketVal = min;
+    // System.err.println("min:" + Instant.ofEpochMilli(min) + "   max: " + Instant.ofEpochMilli(max) + "   gap: " + gap);
+    // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + Instant.ofEpochMilli(minBucketVal));
+    for (long value : sortedValues) {
+      // System.err.println("value: " + Instant.ofEpochMilli(value));
+      while (value >= gap.addTo(minBucketVal)) {
+        ++bucketNum;
+        minBucketVal = gap.addTo(minBucketVal);
+        // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + Instant.ofEpochMilli(minBucketVal));
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i), docValuesField, Instant.ofEpochMilli(values.get(i)).toString(),
+          nonDocValuesField, Instant.ofEpochMilli(values.get(i)).toString()));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + Instant.ofEpochMilli(minBucketVal).toString() 
+          + "'][.='" + bucketCount[i] + "']";
+      minBucketVal = gap.addTo(minBucketVal);
+    }
+    long maxPlusGap = gap.addTo(max);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, 
+        "facet.range.start", Instant.ofEpochMilli(min).toString(),
+        "facet.range.end", Instant.ofEpochMilli(maxPlusGap).toString(),
+        "facet.range.gap", gap.toString()),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, 
+        "facet.range.start", Instant.ofEpochMilli(min).toString(),
+        "facet.range.end", Instant.ofEpochMilli(maxPlusGap).toString(),   
+        "facet.range.gap", gap.toString(), 
+        "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + Instant.ofEpochMilli(minBucketVal).toString() 
+          + "'][.='" + bucketCount[i] + "']";
+      minBucketVal = gap.addTo(minBucketVal);
+    }
+    maxPlusGap = gap.addTo(max);
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, 
+        "facet.range.start", Instant.ofEpochMilli(min).toString(),
+        "facet.range.end", Instant.ofEpochMilli(maxPlusGap).toString(), 
+        "facet.range.gap", gap.toString(), 
+        "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, 
+        "facet.range.start", Instant.ofEpochMilli(min).toString(),
+        "facet.range.end", Instant.ofEpochMilli(maxPlusGap).toString(), 
+        "facet.range.gap", gap.toString(), 
+        "facet.range.method", "dv"),
+        testStrings);
   }
 
   @Test
@@ -1053,27 +1646,31 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDatePointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_dt_mv", getSequentialStringArrayWithDates(20));
-    testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv_dv", getSequentialStringArrayWithDates(20));
+    String[] dates = toStringArray(getRandomInstants(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_dt_mv", dates);
+    testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv_dv", dates);
   }
 
   @Test
   public void testDatePointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv", getSequentialStringArrayWithDates(20), false);
-    testPointFieldMultiValuedExactQuery("number_p_dt_ni_ns_mv", getSequentialStringArrayWithDates(20), false);
+    String[] dates = toStringArray(getRandomInstants(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv", dates, false);
+    testPointFieldMultiValuedExactQuery("number_p_dt_ni_ns_mv", dates, false);
   }
   
   @Test
   public void testDatePointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_dt_mv", "date", getSequentialStringArrayWithDates(20));
-    testPointFieldMultiValuedReturn("number_p_dt_ni_mv_dv", "date", getSequentialStringArrayWithDates(20));
-    testPointFieldMultiValuedReturn("number_p_dt_dv_ns_mv", "date", getSequentialStringArrayWithDates(20));
+    String[] dates = toStringArray(getRandomInstants(20, false));
+    testPointFieldMultiValuedReturn("number_p_dt_mv", "date", dates);
+    testPointFieldMultiValuedReturn("number_p_dt_ni_mv_dv", "date", dates);
+    testPointFieldMultiValuedReturn("number_p_dt_dv_ns_mv", "date", dates);
   }
 
   @Test
   public void testDatePointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_dt_mv", "date", getSequentialStringArrayWithDates(20));
-    testPointFieldMultiValuedRangeQuery("number_p_dt_ni_mv_dv", "date", getSequentialStringArrayWithDates(20));
+    String[] dates = toStringArray(getRandomInstants(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_dt_mv", "date", dates);
+    testPointFieldMultiValuedRangeQuery("number_p_dt_ni_mv_dv", "date", dates);
   }
 
   @Test
@@ -1089,7 +1686,8 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDatePointMultiValuedFunctionQuery() throws Exception {
-    testPointMultiValuedFunctionQuery("number_p_dt_mv", "number_p_dt_mv_dv", "date", getSequentialStringArrayWithDates(20));
+    String[] dates = toStringArray(getRandomInstants(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointMultiValuedFunctionQuery("number_p_dt_mv", "number_p_dt_mv_dv", "date", dates);
   }
 
   @Test
@@ -1097,9 +1695,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
     if (!Boolean.getBoolean("enable.update.log")) {
       return;
     }
-    testDatePointFieldsAtomicUpdates("number_p_dt", "date");
-    testDatePointFieldsAtomicUpdates("number_p_dt_dv", "date");
-    testDatePointFieldsAtomicUpdates("number_p_dt_dv_ns", "date");
+    testDatePointFieldsAtomicUpdates("number_p_dt");
+    testDatePointFieldsAtomicUpdates("number_p_dt_dv");
+    testDatePointFieldsAtomicUpdates("number_p_dt_dv_ns");
   }
 
   @Test
@@ -1107,9 +1705,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
     if (!Boolean.getBoolean("enable.update.log")) {
       return;
     }
-    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_mv", "date");
-    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_ni_mv_dv", "date");
-    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_dv_ns_mv", "date");
+    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_mv");
+    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_ni_mv_dv");
+    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_dv_ns_mv");
   }
 
   @Test
@@ -1122,45 +1720,59 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testDatePointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_dt_ni", getSequentialStringArrayWithDates(10));
-    doTestFieldNotIndexed("number_p_dt_ni_mv", getSequentialStringArrayWithDates(10));
+    String[] dates = toStringArray(getRandomInstants(10, false));
+    doTestFieldNotIndexed("number_p_dt_ni", dates);
+    doTestFieldNotIndexed("number_p_dt_ni_mv", dates);
   }
   
   @Test
   public void testIndexOrDocValuesQuery() throws Exception {
-    String[] fieldTypeNames = new String[]{"_p_i", "_p_l", "_p_d", "_p_f"};
-    FieldType[] fieldTypes = new FieldType[]{new IntPointField(), new LongPointField(), new DoublePointField(), new FloatPointField()};
-    assert fieldTypeNames.length == fieldTypes.length;
+    String[] fieldTypeNames = new String[] { "_p_i", "_p_l", "_p_d", "_p_f", "_p_dt" };
+    FieldType[] fieldTypes = new FieldType[]
+        { new IntPointField(), new LongPointField(), new DoublePointField(), new FloatPointField(), new DatePointField() };
+    String[] ints = toStringArray(getRandomInts(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] longs = toStringArray(getRandomLongs(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] doubles = toStringArray(getRandomDoubles(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] floats = toStringArray(getRandomFloats(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] dates = toStringArray(getRandomInstants(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] min = new String[] { ints[0], longs[0], doubles[0], floats[0], dates[0] };
+    String[] max = new String[] { ints[1], longs[1], doubles[1], floats[1], dates[1] };
+    assert fieldTypeNames.length == fieldTypes.length
+        && fieldTypeNames.length == max.length
+        && fieldTypeNames.length == min.length;
     for (int i = 0; i < fieldTypeNames.length; i++) {
       SchemaField fieldIndexed = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i]);
       SchemaField fieldIndexedAndDv = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i] + "_dv");
       SchemaField fieldIndexedMv = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i] + "_mv");
       SchemaField fieldIndexedAndDvMv = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i] + "_mv_dv");
-      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexed, "0", "10", true, true) instanceof PointRangeQuery);
-      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDv, "0", "10", true, true) instanceof IndexOrDocValuesQuery);
-      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedMv, "0", "10", true, true) instanceof PointRangeQuery);
-      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDvMv, "0", "10", true, true) instanceof IndexOrDocValuesQuery);
-      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexed, "0") instanceof PointRangeQuery);
-      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDv, "0") instanceof IndexOrDocValuesQuery);
-      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedMv, "0") instanceof PointRangeQuery);
-      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDvMv, "0") instanceof IndexOrDocValuesQuery);
+      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexed, min[i], max[i], true, true) instanceof PointRangeQuery);
+      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDv, min[i], max[i], true, true) instanceof IndexOrDocValuesQuery);
+      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedMv, min[i], max[i], true, true) instanceof PointRangeQuery);
+      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDvMv, min[i], max[i], true, true) instanceof IndexOrDocValuesQuery);
+      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexed, min[i]) instanceof PointRangeQuery);
+      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDv, min[i]) instanceof IndexOrDocValuesQuery);
+      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedMv, min[i]) instanceof PointRangeQuery);
+      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDvMv, min[i]) instanceof IndexOrDocValuesQuery);
     }
   }
   
   public void testInternals() throws IOException {
-    String[] types = new String[]{"i", "l", "f", "d"};
+    String[] types = new String[]{"i", "l", "f", "d", "dt"};
+    String[][] values = new String[][] {
+        toStringArray(getRandomInts(10, false)),
+        toStringArray(getRandomLongs(10, false)),
+        toStringArray(getRandomFloats(10, false)),
+        toStringArray(getRandomDoubles(10, false)),
+        toStringArray(getRandomInstants(10, false))
+    };
+    assertEquals(types.length, values.length);
     Set<String> typesTested = new HashSet<>();
-    for (String type:types) {
+    for (int i = 0 ; i < types.length ; ++i) {
       for (String suffix:FIELD_SUFFIXES) {
-        doTestInternals("number_p_" + type + suffix, getSequentialStringArrayWithInts(10));
-        typesTested.add("*_p_" + type + suffix);
+        doTestInternals("number_p_" + types[i] + suffix, values[i]);
+        typesTested.add("*_p_" + types[i] + suffix);
       }
     }
-    for (String suffix:FIELD_SUFFIXES) {
-      doTestInternals("number_p_dt" + suffix, getSequentialStringArrayWithDates(10));
-      typesTested.add("*_p_dt" + suffix);
-    }
-
     assertEquals("Missing types in the test", dynFieldRegexesForType(PointField.class), typesTested);
   }
   
@@ -1197,24 +1809,43 @@ public class TestPointFields extends SolrTestCaseJ4 {
   }
 
   private List<Double> getRandomDoubles(int length, boolean missingVals) {
-    return getRandomList(length, missingVals, 
-        () -> random().nextDouble() * Double.MAX_VALUE * (random().nextBoolean() ? 1.D : -1.D));
+    return getRandomList(length, missingVals, () -> {
+      Double d = Double.NaN; 
+      while (d.isNaN()) {
+        d = Double.longBitsToDouble(random().nextLong());
+      }
+      return d; 
+    });
   }
 
   private List<Float> getRandomFloats(int length, boolean missingVals) {
-    return getRandomList(length, missingVals,
-        () -> random().nextFloat() * Float.MAX_VALUE * (random().nextBoolean() ? 1.f : -1.f));
+    return getRandomList(length, missingVals, () -> {
+      Float f = Float.NaN;
+      while (f.isNaN()) {
+        f = Float.intBitsToFloat(random().nextInt());
+      }
+      return f;
+    });
+  }
+
+  private List<Integer> getRandomInts(int length, boolean missingVals, int bound) {
+    return getRandomList(length, missingVals, () -> random().nextInt() % bound);
   }
 
   private List<Integer> getRandomInts(int length, boolean missingVals) {
     return getRandomList(length, missingVals, () -> random().nextInt());
   }
 
-  private List<Long> getRandomLongs(int length, boolean missingVals){
+  private List<Long> getRandomLongs(int length, boolean missingVals, long bound) {
+    assert bound > 0L;
+    return getRandomList(length, missingVals, () -> random().nextLong() % bound); // see Random.nextInt(int bound)
+  }
+
+  private List<Long> getRandomLongs(int length, boolean missingVals) {
     return getRandomList(length, missingVals, () -> random().nextLong());
   }
 
-  private List<Instant> getRandomInstants(int length, boolean missingVals){
+  private List<Instant> getRandomInstants(int length, boolean missingVals) {
     return getRandomList(length, missingVals, () -> Instant.ofEpochMilli(random().nextLong()));
   }
   
@@ -1272,47 +1903,46 @@ public class TestPointFields extends SolrTestCaseJ4 {
     doTestIntPointFieldExactQuery(field, testLong, true);
   }
 
+  private String getTestString(boolean searchable, int numFound) {
+    return "//*[@numFound='" + (searchable ? Integer.toString(numFound) : "0") + "']";
+  }
+  
   /**
    * @param field the field to use for indexing and searching against
    * @param testLong set to true if "field" is expected to support long values, false if only integers
    * @param searchable set to true if searches against "field" should succeed, false if field is only stored and searches should always get numFound=0
    */
   private void doTestIntPointFieldExactQuery(final String field, final boolean testLong, final boolean searchable) throws Exception {
-    final String MATCH_ONE = "//*[@numFound='" + (searchable ? "1" : "0") + "']";
-    final String MATCH_TWO = "//*[@numFound='" + (searchable ? "2" : "0") + "']";
-
-    for (int i=0; i < 10; i++) {
-      assertU(adoc("id", String.valueOf(i), field, String.valueOf(i+1)));
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    Map<String,Integer> randCount = new HashMap<>(numValues);
+    String[] rand = testLong ? toStringArray(getRandomLongs(numValues, false))
+                             : toStringArray(getRandomInts(numValues, false));
+    for (int i = 0 ; i < numValues ; i++) {
+      randCount.merge(rand[i], 1, (a, b) -> a + b); // count unique values
+      assertU(adoc("id", String.valueOf(i), field, rand[i]));
     }
     assertU(commit());
-    for (int i = 0; i < 10; i++) {
-      assertQ(req("q", field + ":"+(i+1), "fl", "id, " + field), 
-          MATCH_ONE);
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertQ(req("q", field + ":" + (rand[i].startsWith("-") ? "\\" : "") + rand[i],
+          "fl", "id," + field), getTestString(searchable, randCount.get(rand[i])));
     }
     
-    for (int i = 0; i < 10; i++) {
-      assertQ(req("debug", "true", "q", field + ":" + (i+1) + " OR " + field + ":" + ((i+1)%10 + 1)), MATCH_TWO);
+    StringBuilder builder = new StringBuilder();
+    for (String value : randCount.keySet()) {
+      if (builder.length() != 0) {
+        builder.append(" OR ");
+      }
+      if (value.startsWith("-")) {
+        builder.append("\\"); // escape negative sign
+      }
+      builder.append(value);
     }
+    assertQ(req("debug", "true", "q", field + ":(" + builder.toString() + ")"), getTestString(searchable, numValues));
     
     assertU(adoc("id", String.valueOf(Integer.MAX_VALUE), field, String.valueOf(Integer.MAX_VALUE)));
     assertU(commit());
-    assertQ(req("q", field + ":"+Integer.MAX_VALUE, "fl", "id, " + field), 
-        MATCH_ONE);
-    
-    if (testLong) {
-      for (long i = (long)Integer.MAX_VALUE; i < (long)Integer.MAX_VALUE + 10; i++) {
-        assertU(adoc("id", String.valueOf(i), field, String.valueOf(i+1)));
-      }
-      assertU(commit());
-      for (long i = (long)Integer.MAX_VALUE; i < (long)Integer.MAX_VALUE + 10; i++) {
-        assertQ(req("q", field + ":"+(i+1), "fl", "id, " + field), 
-                MATCH_ONE);
-      }
-      assertU(adoc("id", String.valueOf(Long.MAX_VALUE), field, String.valueOf(Long.MAX_VALUE)));
-      assertU(commit());
-      assertQ(req("q", field + ":"+Long.MAX_VALUE, "fl", "id, " + field), 
-              MATCH_ONE);
-    }
+    assertQ(req("q", field + ":"+Integer.MAX_VALUE, "fl", "id, " + field), getTestString(searchable, 1));
     
     clearIndex();
     assertU(commit());
@@ -1489,54 +2119,6 @@ public class TestPointFields extends SolrTestCaseJ4 {
         SolrException.ErrorCode.BAD_REQUEST);
   }
   
-  private void doTestIntPointFieldRangeFacet(String docValuesField, String nonDocValuesField) throws Exception {
-    for (int i = 0; i < 10; i++) {
-      assertU(adoc("id", String.valueOf(i), docValuesField, String.valueOf(i), nonDocValuesField, String.valueOf(i)));
-    }
-    assertU(commit());
-    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
-    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
-    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2"), 
-        "//*[@numFound='10']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
-    
-    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "dv"), 
-        "//*[@numFound='10']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
-    
-    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
-    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
-    // Range Faceting with method = filter should work
-    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "filter"), 
-        "//*[@numFound='10']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
-    
-    // this should actually use filter method instead of dv
-    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "dv"), 
-        "//*[@numFound='10']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
-  }
-
   private void doTestIntPointFunctionQuery(String field, String type) throws Exception {
     for (int i = 9; i >= 0; i--) {
       assertU(adoc("id", String.valueOf(i), field, String.valueOf(i)));
@@ -1600,7 +2182,7 @@ public class TestPointFields extends SolrTestCaseJ4 {
   }
 
   
-  private void testPointStats(String field, String dvField, String[] numbers, double min, double max, String count, String missing, double delta) {
+  private void testPointStats(String field, String dvField, String[] numbers, double min, double max, int count, int missing, double delta) {
     String minMin = String.valueOf(min - Math.abs(delta*min));
     String maxMin = String.valueOf(min + Math.abs(delta*min));
     String minMax = String.valueOf(max - Math.abs(delta*max));
@@ -1614,10 +2196,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
     assertTrue(h.getCore().getLatestSchema().getField(dvField).getType() instanceof PointField);
     assertQ(req("q", "*:*", "fl", "id, " + dvField, "stats", "true", "stats.field", dvField), 
         "//*[@numFound='11']",
-        "//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/double[@name='min'][.>='" + minMin + "']",
-        "//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/double[@name='min'][.<='" + maxMin+ "']",
-        "//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/double[@name='max'][.>='" + minMax + "']",
-        "//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dv

<TRUNCATED>

[5/6] lucene-solr:branch_7_0: SOLR-10796: TestPointFields: increase randomized testing of non-trivial values

Posted by sa...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0511aeb5/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/TestPointFields.java b/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
index a1d2260..3dac18c 100644
--- a/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
+++ b/solr/core/src/test/org/apache/solr/schema/TestPointFields.java
@@ -17,17 +17,24 @@
 package org.apache.solr.schema;
 
 import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
 import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
@@ -69,13 +76,13 @@ import org.junit.Test;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
-/**
- * Tests for PointField functionality
- *
- *
- */
+/** Tests for PointField functionality */
 public class TestPointFields extends SolrTestCaseJ4 {
-  
+
+  // long overflow can occur in some date calculations if gaps are too large, so we limit to a million years BC & AD.
+  private static final long MIN_DATE_EPOCH_MILLIS = LocalDateTime.parse("-1000000-01-01T00:00:00").toInstant(ZoneOffset.ofHours(0)).toEpochMilli();
+  private static final long MAX_DATE_EPOCH_MILLIS = LocalDateTime.parse("+1000000-01-01T00:00:00").toInstant(ZoneOffset.ofHours(0)).toEpochMilli();
+
   private static final String[] FIELD_SUFFIXES = new String[] {
       "", "_dv", "_mv", "_mv_dv", "_ni", "_ni_dv", "_ni_dv_ns", "_ni_dv_ns_mv", 
       "_ni_mv", "_ni_mv_dv", "_ni_ns", "_ni_ns_mv", "_dv_ns", "_ni_ns_dv", "_dv_ns_mv",
@@ -115,9 +122,11 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testIntPointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_i", "int", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99"});
-    testPointFieldReturn("number_p_i_dv_ns", "int", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99"});
-    testPointFieldReturn("number_p_i_ni", "int", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99"});
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] ints = toStringArray(getRandomInts(numValues, false));
+    testPointFieldReturn("number_p_i", "int", ints);
+    testPointFieldReturn("number_p_i_dv_ns", "int", ints);
+    testPointFieldReturn("number_p_i_ni", "int", ints);
   }
   
   @Test
@@ -129,9 +138,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testIntPointFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni", "42");
-    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns", "42");
-    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns_mv", "42", "666");
+    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni", toStringArray(getRandomInts(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns", toStringArray(getRandomInts(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_i_ni_ns_mv", toStringArray(getRandomInts(numValues, false)));
   }
   
   @Test
@@ -162,8 +172,8 @@ public class TestPointFields extends SolrTestCaseJ4 {
     for (String r : Arrays.asList("*_p_i_ni", "*_p_i_ni_ns")) {
       assertTrue(r, regexToTest.remove(r));
       String field = r.replace("*", "number");
-      doTestPointFieldSortError(field, "w/o docValues", "42");
-      doTestPointFieldFunctionQueryError(field, "w/o docValues", "42");
+      doTestPointFieldSortError(field, "w/o docValues", toStringArray(getRandomInts(1, false)));
+      doTestPointFieldFunctionQueryError(field, "w/o docValues", toStringArray(getRandomInts(1, false)));
     }
     
     for (String r : Arrays.asList("*_p_i_mv", "*_p_i_ni_mv", "*_p_i_ni_mv_dv", "*_p_i_ni_dv_ns_mv",
@@ -172,10 +182,11 @@ public class TestPointFields extends SolrTestCaseJ4 {
                                   "*_p_i_mv_sml", "*_p_i_mv_dv_sml", "*_p_i_ni_mv_dv_sml")) {
       assertTrue(r, regexToTest.remove(r));
       String field = r.replace("*", "number");
-      doTestPointFieldSortError(field, "multivalued", "42");
-      doTestPointFieldSortError(field, "multivalued", "42", "666");
-      doTestPointFieldFunctionQueryError(field, "multivalued", "42");
-      doTestPointFieldFunctionQueryError(field, "multivalued", "42", "666");
+      doTestPointFieldSortError(field, "multivalued", toStringArray(getRandomInts(1, false)));
+      int numValues = 2 * RANDOM_MULTIPLIER;
+      doTestPointFieldSortError(field, "multivalued", toStringArray(getRandomInts(numValues, false)));
+      doTestPointFieldFunctionQueryError(field, "multivalued", toStringArray(getRandomInts(1, false)));
+      doTestPointFieldFunctionQueryError(field, "multivalued", toStringArray(getRandomInts(numValues, false)));
    }
     
     assertEquals("Missing types in the test", Collections.<String>emptySet(), regexToTest);
@@ -184,68 +195,214 @@ public class TestPointFields extends SolrTestCaseJ4 {
   @Test
   public void testIntPointFieldFacetField() throws Exception {
     testPointFieldFacetField("number_p_i", "number_p_i_dv", getSequentialStringArrayWithInts(10));
+    clearIndex();
+    assertU(commit());
+    testPointFieldFacetField("number_p_i", "number_p_i_dv", toStringArray(getRandomInts(10, false)));
   }
 
   @Test
   public void testIntPointFieldRangeFacet() throws Exception {
-    doTestIntPointFieldRangeFacet("number_p_i_dv", "number_p_i");
+    String docValuesField = "number_p_i_dv";
+    String nonDocValuesField = "number_p_i";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Integer> values;
+    List<Integer> sortedValues;
+    int max;
+    do {
+      values = getRandomInts(numValues, false);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+    } while ((max = sortedValues.get(sortedValues.size() - 1)) >= Integer.MAX_VALUE - numValues); // leave room for rounding 
+    int min = sortedValues.get(0);
+    int gap = (int)(((long)(max + numValues) - (long)min) / (long)numBuckets);
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    int minBucketVal = min;
+    for (Integer value : sortedValues) {
+      while (((long)value - (long)minBucketVal) >= (long)gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i), docValuesField, String.valueOf(values.get(i)), nonDocValuesField, String.valueOf(values.get(i))));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap)),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
   }
 
   @Test
   public void testIntPointStats() throws Exception {
-    testPointStats("number_p_i", "number_p_i_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
-        0D, 9D, "10", "1", 0D);
-    testPointStats("number_p_i", "number_p_i_mv_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
-        0D, 9D, "10", "1", 0D);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    // don't produce numbers with exponents, since XPath comparison operators can't handle them
+    List<Integer> values  = getRandomInts(numValues, false, 9999999);
+    System.err.println(Arrays.toString(values.toArray(new Integer[values.size()])));
+    List<Integer> sortedValues = values.stream().sorted().collect(Collectors.toList());
+    double min = (double)sortedValues.get(0);
+    double max = (double)sortedValues.get(sortedValues.size() - 1);
+
+    String[] valArray = toStringArray(values);
+    testPointStats("number_p_i", "number_p_i_dv", valArray, min, max, numValues, 1, 0D);
+    testPointStats("number_p_i", "number_p_i_mv_dv", valArray, min, max, numValues, 1, 0D);
   }
 
   @Test
   public void testIntPointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_i_mv", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedExactQuery("number_p_i_ni_mv_dv", getSequentialStringArrayWithInts(20));
+    String[] ints = toStringArray(getRandomInts(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_i_mv", ints);
+    testPointFieldMultiValuedExactQuery("number_p_i_ni_mv_dv", ints);
   }
 
   @Test
   public void testIntPointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_i_ni_mv", getSequentialStringArrayWithInts(20), false);
-    testPointFieldMultiValuedExactQuery("number_p_i_ni_ns_mv", getSequentialStringArrayWithInts(20), false);
+    String[] ints = toStringArray(getRandomInts(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_i_ni_mv", ints, false);
+    testPointFieldMultiValuedExactQuery("number_p_i_ni_ns_mv", ints, false);
   }
   
   @Test
   public void testIntPointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_i_mv", "int", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedReturn("number_p_i_ni_mv_dv", "int", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedReturn("number_p_i_dv_ns_mv", "int", getSequentialStringArrayWithInts(20));
+    String[] ints = toStringArray(getRandomInts(20, false));
+    testPointFieldMultiValuedReturn("number_p_i_mv", "int", ints);
+    testPointFieldMultiValuedReturn("number_p_i_ni_mv_dv", "int", ints);
+    testPointFieldMultiValuedReturn("number_p_i_dv_ns_mv", "int", ints);
   }
   
   @Test
   public void testIntPointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_i_mv", "int", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedRangeQuery("number_p_i_ni_mv_dv", "int", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedRangeQuery("number_p_i_mv_dv", "int", getSequentialStringArrayWithInts(20));
+    String[] ints = toStringArray(getRandomInts(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_i_mv", "int", ints);
+    testPointFieldMultiValuedRangeQuery("number_p_i_ni_mv_dv", "int", ints);
+    testPointFieldMultiValuedRangeQuery("number_p_i_mv_dv", "int", ints);
   }
   
   @Test
   public void testIntPointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_i_ni", getSequentialStringArrayWithInts(10));
-    doTestFieldNotIndexed("number_p_i_ni_mv", getSequentialStringArrayWithInts(10));
+    String[] ints = toStringArray(getRandomInts(10, false));
+    doTestFieldNotIndexed("number_p_i_ni", ints);
+    doTestFieldNotIndexed("number_p_i_ni_mv", ints);
   }
   
   //TODO MV SORT?
   @Test
   public void testIntPointFieldMultiValuedFacetField() throws Exception {
     testPointFieldMultiValuedFacetField("number_p_i_mv", "number_p_i_mv_dv", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedFacetField("number_p_i_mv", "number_p_i_mv_dv", toStringArray(getRandomInts(20, false)));
+    String[] randomSortedInts = toStringArray(getRandomInts(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedFacetField("number_p_i_mv", "number_p_i_mv_dv", randomSortedInts);
   }
 
   @Test
   public void testIntPointFieldMultiValuedRangeFacet() throws Exception {
-    doTestIntPointFieldMultiValuedRangeFacet("number_p_i_mv_dv", "number_p_i_mv");
+    String docValuesField = "number_p_i_mv_dv";
+    String nonDocValuesField = "number_p_i_mv";
+    int numValues = 20 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Integer> values;
+    List<PosVal<Integer>> sortedValues;
+    int max;
+    do {
+      values = getRandomInts(numValues, false);
+      sortedValues = toAscendingPosVals(values, true);
+    } while ((max = sortedValues.get(sortedValues.size() - 1).val) >= Integer.MAX_VALUE - numValues); // leave room for rounding
+    int min = sortedValues.get(0).val;
+    int gap = (int)(((long)(max + numValues) - (long)min) / (long)numBuckets);
+    List<Set<Integer>> docIdBucket = new ArrayList<>(numBuckets);
+    for (int i = 0 ; i < numBuckets ; ++i) {
+      docIdBucket.add(new HashSet<>());
+    }
+    int bucketNum = 0;
+    int minBucketVal = min;
+    for (PosVal<Integer> value : sortedValues) {
+      while (value.val - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+      }
+      docIdBucket.get(bucketNum).add(value.pos / 2); // each doc gets two consecutive values 
+    }
+    for (int i = 0 ; i < numValues ; i += 2) {
+      assertU(adoc("id", String.valueOf(i / 2),
+          docValuesField, String.valueOf(values.get(i)),
+          docValuesField, String.valueOf(values.get(i + 1)),
+          nonDocValuesField, String.valueOf(values.get(i)),
+          nonDocValuesField, String.valueOf(values.get(i + 1))));
+    }
+    assertU(commit());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    minBucketVal = min;
+    testStrings[numBuckets] = "//*[@numFound='" + (numValues / 2) + "']";
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + docIdBucket.get(i).size() + "']";
+    }
+
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "indent", "on"),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv", "indent", "on"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + docIdBucket.get(i).size() + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter", "indent", "on"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv", "indent", "on"),
+        testStrings);
   }
 
   @Test
-  public void testIntPointMultiValuedFunctionQuery() throws Exception {
+  public void testIntPointMultiValuedFunctionQuery() throws Exception {       
     testPointMultiValuedFunctionQuery("number_p_i_mv", "number_p_i_mv_dv", "int", getSequentialStringArrayWithInts(20));
+    testPointMultiValuedFunctionQuery("number_p_i_mv", "number_p_i_mv_dv", "int",
+        toStringArray(getRandomInts(20, false).stream().sorted().collect(Collectors.toList())));
   }
   
   @Test
@@ -280,6 +437,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
       this.pos = pos;
       this.val = val;
     }
+    public String toString() {
+      return "(" + pos + ": " + val.toString() + ")";
+    }
   }
 
   /** Primary sort by value, with nulls either first or last as specified, and then secondary sort by position. */
@@ -345,33 +505,29 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDoublePointFieldExactQuery() throws Exception {
-    doTestFloatPointFieldExactQuery("number_d");
-    doTestFloatPointFieldExactQuery("number_p_d");
-    doTestFloatPointFieldExactQuery("number_p_d_mv");
-    doTestFloatPointFieldExactQuery("number_p_d_dv");
-    doTestFloatPointFieldExactQuery("number_p_d_mv_dv");
-    doTestFloatPointFieldExactQuery("number_p_d_ni_dv");
-    doTestFloatPointFieldExactQuery("number_p_d_ni_ns_dv");
-    doTestFloatPointFieldExactQuery("number_p_d_ni_dv_ns");
-    doTestFloatPointFieldExactQuery("number_p_d_ni_mv_dv");
+    doTestFloatPointFieldExactQuery("number_d", true);
+    doTestFloatPointFieldExactQuery("number_p_d", true);
+    doTestFloatPointFieldExactQuery("number_p_d_mv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_dv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_mv_dv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_dv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_ns_dv", true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_dv_ns", true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_mv_dv", true);
   }
   
   @Test
   public void testDoublePointFieldNonSearchableExactQuery() throws Exception {
-    doTestFloatPointFieldExactQuery("number_p_d_ni", false);
-    doTestFloatPointFieldExactQuery("number_p_d_ni_ns", false);
+    doTestFloatPointFieldExactQuery("number_p_d_ni", false, true);
+    doTestFloatPointFieldExactQuery("number_p_d_ni_ns", false, true);
   }
  
   @Test
   public void testDoublePointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_d", "double", new String[]{"0.0", "1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
-    testPointFieldReturn("number_p_d_dv_ns", "double", new String[]{"0.0", "1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
-    String[] arr = new String[atLeast(10)];
-    for (int i = 0; i < arr.length; i++) {
-      double rand = random().nextDouble() * 10;
-      arr[i] = String.valueOf(rand);
-    }
-    testPointFieldReturn("number_p_d", "double", arr);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] doubles = toStringArray(getRandomDoubles(numValues, false));
+    testPointFieldReturn("number_p_d", "double", doubles);
+    testPointFieldReturn("number_p_d_dv_ns", "double", doubles);
   }
   
   @Test
@@ -383,9 +539,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testDoubleFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni", "42.3");
-    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns", "42.3");
-    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns_mv", "42.3", "-66.6");
+    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni", toStringArray(getRandomDoubles(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns", toStringArray(getRandomDoubles(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_d_ni_ns_mv", toStringArray(getRandomDoubles(numValues, false)));
   }
   
   
@@ -446,41 +603,121 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDoublePointFieldRangeFacet() throws Exception {
-    doTestFloatPointFieldRangeFacet("number_p_d_dv", "number_p_d");
+    String docValuesField = "number_p_d_dv";
+    String nonDocValuesField = "number_p_d";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Double> values, sortedValues;
+    double min, max, gap, buffer;
+    do {
+      values = getRandomDoubles(numValues, false);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+      min = sortedValues.get(0);
+      max = sortedValues.get(sortedValues.size() - 1);
+      buffer = BigDecimal.valueOf(max).subtract(BigDecimal.valueOf(min))
+          .divide(BigDecimal.valueOf(numValues), RoundingMode.HALF_UP)
+          .divide(BigDecimal.valueOf(2.0D), RoundingMode.HALF_UP).doubleValue();
+      gap = BigDecimal.valueOf(max + buffer).subtract(BigDecimal.valueOf(min - buffer))
+          .divide(BigDecimal.valueOf(numBuckets), RoundingMode.HALF_UP).doubleValue();
+    } while (max >= Double.MAX_VALUE - buffer || min <= -Double.MAX_VALUE + buffer);
+    // System.err.println("min: " + min + "   max: " + max + "   gap: " + gap + "   buffer: " + buffer);
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    double minBucketVal = min - buffer;
+    // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + minBucketVal);
+    for (double value : sortedValues) {
+      // System.err.println("value: " + value);
+      while (value - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+        // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + minBucketVal);
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i),
+          docValuesField, String.valueOf(values.get(i)), nonDocValuesField, String.valueOf(values.get(i))));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min - buffer;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap)),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min - buffer;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
   }
 
   @Test
   public void testDoublePointStats() throws Exception {
-    testPointStats("number_p_d", "number_p_d_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-        -10.0D, 9.9D, "10", "1", 1E-10D);
-    testPointStats("number_p_d_mv", "number_p_d_mv_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-        -10.0D, 9.9D, "10", "1", 1E-10D);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    // don't produce numbers with exponents, since XPath comparison operators can't handle them: 7 digits of precision
+    List<Float> values  = getRandomInts(numValues, false, 9999999).stream()
+        .map(v -> (float)((double)v * Math.pow(10D, -1 * random().nextInt(8)))).collect(Collectors.toList());
+    System.err.println(Arrays.toString(values.toArray(new Float[values.size()])));
+    List<Float> sortedValues = values.stream().sorted().collect(Collectors.toList());
+    double min = (double)sortedValues.get(0);
+    double max = (double)sortedValues.get(sortedValues.size() - 1);
+
+    String[] valArray = toStringArray(values);
+    testPointStats("number_p_d", "number_p_d_dv", valArray, min, max, numValues, 1, 1E-7D);
+    testPointStats("number_p_d", "number_p_d_mv_dv", valArray, min, max, numValues, 1, 1E-7D);
   }
   
   @Test
   public void testDoublePointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_d_mv", toStringArray(getRandomDoubles(20, false)));
-    testPointFieldMultiValuedExactQuery("number_p_d_ni_mv_dv", toStringArray(getRandomDoubles(20, false)));
+    String[] doubles = toStringArray(getRandomDoubles(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_d_mv", doubles);
+    testPointFieldMultiValuedExactQuery("number_p_d_ni_mv_dv", doubles);
   }
   
   @Test
   public void testDoublePointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_d_ni_mv", toStringArray(getRandomDoubles(20, false)), false);
-    testPointFieldMultiValuedExactQuery("number_p_d_ni_ns_mv", toStringArray(getRandomDoubles(20, false)), false);
+    String[] doubles = toStringArray(getRandomDoubles(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_d_ni_mv", doubles, false);
+    testPointFieldMultiValuedExactQuery("number_p_d_ni_ns_mv", doubles, false);
   }
   
   @Test
   public void testDoublePointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_d_mv", "double", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedReturn("number_p_d_ni_mv_dv", "double", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedReturn("number_p_d_dv_ns_mv", "double", getSequentialStringArrayWithDoubles(20));
+    String[] doubles = toStringArray(getRandomDoubles(20, false));
+    testPointFieldMultiValuedReturn("number_p_d_mv", "double", doubles);
+    testPointFieldMultiValuedReturn("number_p_d_ni_mv_dv", "double", doubles);
+    testPointFieldMultiValuedReturn("number_p_d_dv_ns_mv", "double", doubles);
   }
   
   @Test
   public void testDoublePointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_d_mv", "double", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedRangeQuery("number_p_d_ni_mv_dv", "double", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedRangeQuery("number_p_d_mv_dv", "double", getSequentialStringArrayWithDoubles(20));
+    String[] doubles = toStringArray(getRandomDoubles(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_d_mv", "double", doubles);
+    testPointFieldMultiValuedRangeQuery("number_p_d_ni_mv_dv", "double", doubles);
+    testPointFieldMultiValuedRangeQuery("number_p_d_mv_dv", "double", doubles);
   }
   
   @Test
@@ -522,8 +759,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testDoublePointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_d_ni", getSequentialStringArrayWithDoubles(10));
-    doTestFieldNotIndexed("number_p_d_ni_mv", getSequentialStringArrayWithDoubles(10));
+    String[] doubles = toStringArray(getRandomDoubles(10, false));
+    doTestFieldNotIndexed("number_p_d_ni", doubles);
+    doTestFieldNotIndexed("number_p_d_ni_mv", doubles);
   }
   
   
@@ -571,32 +809,28 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testFloatPointFieldExactQuery() throws Exception {
-    doTestFloatPointFieldExactQuery("number_p_f");
-    doTestFloatPointFieldExactQuery("number_p_f_mv");
-    doTestFloatPointFieldExactQuery("number_p_f_dv");
-    doTestFloatPointFieldExactQuery("number_p_f_mv_dv");
-    doTestFloatPointFieldExactQuery("number_p_f_ni_dv");
-    doTestFloatPointFieldExactQuery("number_p_f_ni_ns_dv");
-    doTestFloatPointFieldExactQuery("number_p_f_ni_dv_ns");
-    doTestFloatPointFieldExactQuery("number_p_f_ni_mv_dv");
+    doTestFloatPointFieldExactQuery("number_p_f", false);
+    doTestFloatPointFieldExactQuery("number_p_f_mv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_dv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_mv_dv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_dv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_ns_dv", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_dv_ns", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_mv_dv", false);
   }
   
   @Test
   public void testFloatPointFieldNonSearchableExactQuery() throws Exception {
-    doTestFloatPointFieldExactQuery("number_p_f_ni", false);
-    doTestFloatPointFieldExactQuery("number_p_f_ni_ns", false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni", false, false);
+    doTestFloatPointFieldExactQuery("number_p_f_ni_ns", false, false);
   }
   
   @Test
   public void testFloatPointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_f", "float", new String[]{"0.0", "-1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
-    testPointFieldReturn("number_p_f_dv_ns", "float", new String[]{"0.0", "-1.2", "2.5", "3.02", "0.43", "5.2", "6.01", "74.0", "80.0", "9.9"});
-    String[] arr = new String[atLeast(10)];
-    for (int i = 0; i < arr.length; i++) {
-      float rand = random().nextFloat() * 10;
-      arr[i] = String.valueOf(rand);
-    }
-    testPointFieldReturn("number_p_f", "float", arr);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] floats = toStringArray(getRandomFloats(numValues, false));
+    testPointFieldReturn("number_p_f", "float", floats);
+    testPointFieldReturn("number_p_f_dv_ns", "float", floats);
   }
   
   @Test
@@ -608,9 +842,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testFloatPointFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni", "42.3");
-    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns", "42.3");
-    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns_mv", "42.3", "-66.6");
+    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni", toStringArray(getRandomFloats(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns", toStringArray(getRandomFloats(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_f_ni_ns_mv", toStringArray(getRandomFloats(numValues, false)));
   }
   
   @Test
@@ -669,42 +904,120 @@ public class TestPointFields extends SolrTestCaseJ4 {
   }
 
   @Test
+  @AwaitsFix(bugUrl = "https://issues.apache.org/jira/browse/SOLR-11043")
   public void testFloatPointFieldRangeFacet() throws Exception {
-    doTestFloatPointFieldRangeFacet("number_p_f_dv", "number_p_f");
+    String docValuesField = "number_p_f_dv";
+    String nonDocValuesField = "number_p_f";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Float> values, sortedValues;
+    float min, max, gap, buffer;
+    do {
+      values = getRandomFloats(numValues, false);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+      min = sortedValues.get(0);
+      max = sortedValues.get(sortedValues.size() - 1);
+      buffer = (float)(((double)max - (double)min) / (double)numValues / 2.0D);
+      gap = (float)(((double)max + (double)buffer - (double)min + (double)buffer) / (double)numBuckets);
+    } while (max >= Float.MAX_VALUE - buffer || min <= -Float.MAX_VALUE + buffer); 
+    // System.err.println("min: " + min + "   max: " + max + "   gap: " + gap + "   buffer: " + buffer);
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    float minBucketVal = min - buffer;
+    // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + minBucketVal);
+    for (float value : sortedValues) {
+      // System.err.println("value: " + value);
+      while (value - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+        // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + minBucketVal);
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i), 
+          docValuesField, String.valueOf(values.get(i)), nonDocValuesField, String.valueOf(values.get(i))));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min - buffer;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap)),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min - buffer;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min - buffer),
+        "facet.range.end", String.valueOf(max + buffer), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
   }
 
   @Test
   public void testFloatPointStats() throws Exception {
-    testPointStats("number_p_f", "number_p_f_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-        -10D, 9.9D, "10", "1", 1E-6D);
-    testPointStats("number_p_f_mv", "number_p_f_mv_dv", new String[]{"-10.0", "1.1", "2.2", "3.3", "4.4", "5.5", "6.6", "7.7", "8.8", "9.9"},
-        -10D, 9.9D, "10", "1", 1E-6D);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    // don't produce numbers with exponents, since XPath comparison operators can't handle them: 7 digits of precision
+    List<Float> values  = getRandomInts(numValues, false, 9999999).stream()
+        .map(v -> (float)((double)v * Math.pow(10D, -1 * random().nextInt(8)))).collect(Collectors.toList());
+    System.err.println(Arrays.toString(values.toArray(new Float[values.size()])));
+    List<Float> sortedValues = values.stream().sorted().collect(Collectors.toList());
+    double min = (double)sortedValues.get(0);
+    double max = (double)sortedValues.get(sortedValues.size() - 1);
+
+    String[] valArray = toStringArray(values);
+    testPointStats("number_p_f", "number_p_f_dv", valArray, min, max, numValues, 1, 1E-7D);
+    testPointStats("number_p_f", "number_p_f_mv_dv", valArray, min, max, numValues, 1, 1E-7D);
   }
   
   @Test
   public void testFloatPointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_f_mv", toStringArray(getRandomFloats(20, false)));
-    testPointFieldMultiValuedExactQuery("number_p_f_ni_mv_dv", toStringArray(getRandomFloats(20, false)));
+    String[] floats = toStringArray(getRandomFloats(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_f_mv", floats);
+    testPointFieldMultiValuedExactQuery("number_p_f_ni_mv_dv", floats);
   }
   
   @Test
   public void testFloatPointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_f_ni_mv", toStringArray(getRandomFloats(20, false)), false);
-    testPointFieldMultiValuedExactQuery("number_p_f_ni_ns_mv", toStringArray(getRandomFloats(20, false)), false);
+    String[] floats = toStringArray(getRandomFloats(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_f_ni_mv", floats, false);
+    testPointFieldMultiValuedExactQuery("number_p_f_ni_ns_mv", floats, false);
   }
   
   @Test
   public void testFloatPointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_f_mv", "float", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedReturn("number_p_f_ni_mv_dv", "float", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedReturn("number_p_f_dv_ns_mv", "float", getSequentialStringArrayWithDoubles(20));
+    String[] floats = toStringArray(getRandomFloats(20, false));
+    testPointFieldMultiValuedReturn("number_p_f_mv", "float", floats);
+    testPointFieldMultiValuedReturn("number_p_f_ni_mv_dv", "float", floats);
+    testPointFieldMultiValuedReturn("number_p_f_dv_ns_mv", "float", floats);
   }
   
   @Test
   public void testFloatPointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_f_mv", "float", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedRangeQuery("number_p_f_ni_mv_dv", "float", getSequentialStringArrayWithDoubles(20));
-    testPointFieldMultiValuedRangeQuery("number_p_f_mv_dv", "float", getSequentialStringArrayWithDoubles(20));
+    String[] floats = toStringArray(getRandomFloats(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_f_mv", "float", floats);
+    testPointFieldMultiValuedRangeQuery("number_p_f_ni_mv_dv", "float", floats);
+    testPointFieldMultiValuedRangeQuery("number_p_f_mv_dv", "float", floats);
   }
   
   @Test
@@ -754,8 +1067,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testFloatPointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_f_ni", getSequentialStringArrayWithDoubles(10));
-    doTestFieldNotIndexed("number_p_f_ni_mv", getSequentialStringArrayWithDoubles(10));
+    String[] floats = toStringArray(getRandomFloats(10, false));
+    doTestFieldNotIndexed("number_p_f_ni", floats);
+    doTestFieldNotIndexed("number_p_f_ni_mv", floats);
   }
   
   // Long
@@ -780,8 +1094,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_l", "long", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99", String.valueOf(Long.MAX_VALUE)});
-    testPointFieldReturn("number_p_l_dv_ns", "long", new String[]{"0", "-1", "2", "3", "43", "52", "-60", "74", "80", "99", String.valueOf(Long.MAX_VALUE)});
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] longs = toStringArray(getRandomLongs(numValues, false));
+    testPointFieldReturn("number_p_l", "long", longs);
+    testPointFieldReturn("number_p_l_dv_ns", "long", longs);
   }
   
   @Test
@@ -793,9 +1109,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni", "3333333333");
-    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns", "3333333333");
-    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns_mv", "3333333333", "-4444444444");
+    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni", toStringArray(getRandomLongs(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns", toStringArray(getRandomLongs(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_l_ni_ns_mv", toStringArray(getRandomLongs(numValues, false)));
   }
 
   @Test
@@ -828,8 +1145,8 @@ public class TestPointFields extends SolrTestCaseJ4 {
     for (String r : Arrays.asList("*_p_l_ni", "*_p_l_ni_ns")) {
       assertTrue(r, regexToTest.remove(r));
       String field = r.replace("*", "number");
-      doTestPointFieldSortError(field, "w/o docValues", "4234");
-      doTestPointFieldFunctionQueryError(field, "w/o docValues", "4234");
+      doTestPointFieldSortError(field, "w/o docValues", toStringArray(getRandomLongs(1, false)));
+      doTestPointFieldFunctionQueryError(field, "w/o docValues", toStringArray(getRandomLongs(1, false)));
     }
     
     for (String r : Arrays.asList("*_p_l_mv", "*_p_l_ni_mv", "*_p_l_ni_mv_dv", "*_p_l_ni_dv_ns_mv",
@@ -838,10 +1155,11 @@ public class TestPointFields extends SolrTestCaseJ4 {
                                   "*_p_l_mv_sml", "*_p_l_mv_dv_sml", "*_p_l_ni_mv_dv_sml")) {
       assertTrue(r, regexToTest.remove(r));
       String field = r.replace("*", "number");
-      doTestPointFieldSortError(field, "multivalued", "4234");
-      doTestPointFieldSortError(field, "multivalued", "4234", "66666666");
-      doTestPointFieldFunctionQueryError(field, "multivalued", "4234");
-      doTestPointFieldFunctionQueryError(field, "multivalued", "4234", "66666666");
+      doTestPointFieldSortError(field, "multivalued", toStringArray(getRandomLongs(1, false)));
+      int numValues = 2 * RANDOM_MULTIPLIER;
+      doTestPointFieldSortError(field, "multivalued", toStringArray(getRandomLongs(numValues, false)));
+      doTestPointFieldFunctionQueryError(field, "multivalued", toStringArray(getRandomLongs(1, false)));
+      doTestPointFieldFunctionQueryError(field, "multivalued", toStringArray(getRandomLongs(numValues, false)));
     }
     
     assertEquals("Missing types in the test", Collections.<String>emptySet(), regexToTest);
@@ -857,41 +1175,111 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldRangeFacet() throws Exception {
-    doTestIntPointFieldRangeFacet("number_p_l_dv", "number_p_l");
+    String docValuesField = "number_p_l_dv";
+    String nonDocValuesField = "number_p_l";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Long> values;
+    List<Long> sortedValues;
+    long max;
+    do {
+      values = getRandomLongs(numValues, false);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+    } while ((max = sortedValues.get(sortedValues.size() - 1)) >= Integer.MAX_VALUE - numValues); // leave room for rounding 
+    long min = sortedValues.get(0);
+    long gap = BigInteger.valueOf(max + numValues).subtract(BigInteger.valueOf(min))
+        .divide(BigInteger.valueOf(numBuckets)).longValueExact();
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    long minBucketVal = min;
+    for (Long value : sortedValues) {
+      while (value - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i), docValuesField, String.valueOf(values.get(i)), nonDocValuesField, String.valueOf(values.get(i))));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap)),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + bucketCount[i] + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", String.valueOf(min),
+        "facet.range.end", String.valueOf(max), "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv"),
+        testStrings);
   }
   
   @Test
   public void testLongPointStats() throws Exception {
-    testPointStats("number_p_l", "number_p_l_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
-        0D, 9D, "10", "1", 0D);
-    testPointStats("number_p_l_mv", "number_p_l_mv_dv", new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
-        0D, 9D, "10", "1", 0D);
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    // don't produce numbers with exponents, since XPath comparison operators can't handle them
+    List<Long> values  = getRandomLongs(numValues, false, 9999999L);
+    List<Long> sortedValues = values.stream().sorted().collect(Collectors.toList());
+    double min = (double)sortedValues.get(0);
+    double max = (double)sortedValues.get(sortedValues.size() - 1);
+
+    String[] valArray = toStringArray(values);
+    testPointStats("number_p_l", "number_p_l_dv", valArray, min, max, numValues, 1, 0D);
+    testPointStats("number_p_l", "number_p_l_mv_dv", valArray, min, max, numValues, 1, 0D);
   }
   
   @Test
   public void testLongPointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_l_mv", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedExactQuery("number_p_l_ni_mv_dv", getSequentialStringArrayWithInts(20));
+    String[] ints = toStringArray(getRandomInts(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_l_mv", ints);
+    testPointFieldMultiValuedExactQuery("number_p_l_ni_mv_dv", ints);
   }
   
   @Test
   public void testLongPointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_l_ni_mv", getSequentialStringArrayWithInts(20), false);
-    testPointFieldMultiValuedExactQuery("number_p_l_ni_ns_mv", getSequentialStringArrayWithInts(20), false);
+    String[] longs = toStringArray(getRandomLongs(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_l_ni_mv", longs, false);
+    testPointFieldMultiValuedExactQuery("number_p_l_ni_ns_mv", longs, false);
   }
   
   @Test
   public void testLongPointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_l_mv", "long", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedReturn("number_p_l_ni_mv_dv", "long", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedReturn("number_p_l_dv_ns_mv", "long", getSequentialStringArrayWithInts(20));
+    String[] longs = toStringArray(getRandomLongs(20, false));
+    testPointFieldMultiValuedReturn("number_p_l_mv", "long", longs);
+    testPointFieldMultiValuedReturn("number_p_l_ni_mv_dv", "long", longs);
+    testPointFieldMultiValuedReturn("number_p_l_dv_ns_mv", "long", longs);
   }
   
   @Test
   public void testLongPointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_l_mv", "long", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedRangeQuery("number_p_l_ni_mv_dv", "long", getSequentialStringArrayWithInts(20));
-    testPointFieldMultiValuedRangeQuery("number_p_l_mv_dv", "long", getSequentialStringArrayWithInts(20));
+    String[] longs = toStringArray(getRandomLongs(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_l_mv", "long", longs);
+    testPointFieldMultiValuedRangeQuery("number_p_l_ni_mv_dv", "long", longs);
+    testPointFieldMultiValuedRangeQuery("number_p_l_mv_dv", "long", longs);
   }
   
   @Test
@@ -902,7 +1290,77 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldMultiValuedRangeFacet() throws Exception {
-    doTestIntPointFieldMultiValuedRangeFacet("number_p_l_mv_dv", "number_p_l_mv");
+    String docValuesField = "number_p_l_mv_dv";
+    String nonDocValuesField = "number_p_l_mv";
+    int numValues = 20 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Long> values;
+    List<PosVal<Long>> sortedValues;
+    long max;
+    do {
+      values = getRandomLongs(numValues, false);
+      sortedValues = toAscendingPosVals(values, true);
+    } while ((max = sortedValues.get(sortedValues.size() - 1).val) >= Long.MAX_VALUE - numValues); // leave room for rounding 
+    long min = sortedValues.get(0).val;
+    long gap = BigInteger.valueOf(max + numValues).subtract(BigInteger.valueOf(min))
+        .divide(BigInteger.valueOf(numBuckets)).longValueExact();
+    List<Set<Integer>> docIdBucket = new ArrayList<>(numBuckets);
+    for (int i = 0 ; i < numBuckets ; ++i) {
+      docIdBucket.add(new HashSet<>());
+    }
+    int bucketNum = 0;
+    long minBucketVal = min;
+    for (PosVal<Long> value : sortedValues) {
+      while (value.val - minBucketVal >= gap) {
+        ++bucketNum;
+        minBucketVal += gap;
+      }
+      docIdBucket.get(bucketNum).add(value.pos / 2); // each doc gets two consecutive values 
+    }
+    for (int i = 0 ; i < numValues ; i += 2) {
+      assertU(adoc("id", String.valueOf(i / 2),
+          docValuesField, String.valueOf(values.get(i)),
+          docValuesField, String.valueOf(values.get(i + 1)),
+          nonDocValuesField, String.valueOf(values.get(i)),
+          nonDocValuesField, String.valueOf(values.get(i + 1))));
+    }
+    assertU(commit());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + (numValues / 2) + "']";
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + docIdBucket.get(i).size() + "']";
+    }
+
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "indent", "on"),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv", "indent", "on"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; minBucketVal += gap, ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + minBucketVal + "'][.='" + docIdBucket.get(i).size() + "']";
+    }
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "filter", "indent", "on"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField,
+        "facet.range.start", String.valueOf(min), "facet.range.end", String.valueOf(max),
+        "facet.range.gap", String.valueOf(gap), "facet.range.method", "dv", "indent", "on"),
+        testStrings);
   }
   
   @Test
@@ -939,8 +1397,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testLongPointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_l_ni", getSequentialStringArrayWithInts(10));
-    doTestFieldNotIndexed("number_p_l_ni_mv", getSequentialStringArrayWithInts(10));
+    String[] longs = toStringArray(getRandomLongs(10, false));
+    doTestFieldNotIndexed("number_p_l_ni", longs);
+    doTestFieldNotIndexed("number_p_l_ni_mv", longs);
   }
 
   // Date
@@ -964,12 +1423,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDatePointFieldReturn() throws Exception {
-    testPointFieldReturn("number_p_dt", "date",
-        new String[]{"1995-12-31T23:59:59Z", "1994-02-28T23:59:59Z",
-            "2015-12-31T23:59:59Z", "2000-10-31T23:59:59Z", "1999-12-31T12:59:59Z"});
-    testPointFieldReturn("number_p_dt_dv_ns", "date",
-        new String[]{"1995-12-31T23:59:59Z", "1994-02-28T23:59:59Z",
-            "2015-12-31T23:59:59Z", "2000-10-31T23:59:59Z", "1999-12-31T12:59:59Z"});
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    String[] dates = toStringArray(getRandomInstants(numValues, false));
+    testPointFieldReturn("number_p_dt", "date", dates);
+    testPointFieldReturn("number_p_dt_dv_ns", "date", dates);
   }
 
   @Test
@@ -980,9 +1437,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testDatePointFieldNonSearchableRangeQuery() throws Exception {
-    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni", "1995-12-31T23:59:59Z");
-    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns", "1995-12-31T23:59:59Z");
-    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns_mv", "1995-12-31T23:59:59Z", "2000-10-31T23:59:59Z");
+    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni", toStringArray(getRandomInstants(1, false)));
+    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns", toStringArray(getRandomInstants(1, false)));
+    int numValues = 2 * RANDOM_MULTIPLIER;
+    doTestPointFieldNonSearchableRangeQuery("number_p_dt_ni_ns_mv", toStringArray(getRandomInstants(numValues, false)));
   }
 
   @Test
@@ -1037,12 +1495,147 @@ public class TestPointFields extends SolrTestCaseJ4 {
     testPointFieldFacetField("number_p_dt", "number_p_dt_dv", getSequentialStringArrayWithDates(10));
     clearIndex();
     assertU(commit());
-    testPointFieldFacetField("number_p_dt", "number_p_dt_dv", getSequentialStringArrayWithDates(10));
-  }
+    testPointFieldFacetField("number_p_dt", "number_p_dt_dv", toStringArray(getRandomInstants(10, false)));
+  }
+
+  private static class DateGapCeiling {
+    String calendarUnit = "MILLIS";
+    long inCalendarUnits;
+    boolean negative = false;
+  
+    /** Maximize calendar unit size given initialGapMillis; performs ceiling on each conversion */
+    DateGapCeiling(long initialGapMillis) {
+      negative = initialGapMillis < 0;
+      inCalendarUnits = Math.abs(initialGapMillis);
+      if (inCalendarUnits >= 1000L) {
+        calendarUnit = "SECS";
+        inCalendarUnits = (inCalendarUnits + 999L) / 1000L;
+        if (inCalendarUnits >= 60L) {
+          calendarUnit = "MINUTES";
+          inCalendarUnits = (inCalendarUnits + 59L) / 60L;
+          if (inCalendarUnits >= 60L) {
+            calendarUnit = "HOURS";
+            inCalendarUnits = (inCalendarUnits + 59L) / 60L;
+            if (inCalendarUnits >= 24L) {
+              calendarUnit = "DAYS";
+              inCalendarUnits = (inCalendarUnits + 23L) / 24L;
+              if (inCalendarUnits >= 12L) {
+                calendarUnit = "MONTHS";
+                inCalendarUnits = (inCalendarUnits + 11L) / 12L;
+                if ((inCalendarUnits * 16) >= 487) {  // 487 = 365.25 / 12 * 16   (365.25 days/year, -ish)
+                  calendarUnit = "YEARS";
+                  inCalendarUnits = (16L * inCalendarUnits + 486) / 487L; 
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    @Override
+    public String toString() {
+      return (negative ? "-" : "+") + inCalendarUnits + calendarUnit;
+    }
 
+    public long addTo(long millis) {  // Instant.plus() doesn't work with estimated durations (MONTHS and YEARS)
+      LocalDateTime time = LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneOffset.ofHours(0));
+      if (negative) {
+        time = time.minus(inCalendarUnits, DateMathParser.CALENDAR_UNITS.get(calendarUnit));
+      } else {
+        time = time.plus(inCalendarUnits, DateMathParser.CALENDAR_UNITS.get(calendarUnit));
+      }
+      return time.atZone(ZoneOffset.ofHours(0)).toInstant().toEpochMilli();
+    }
+  }
+  
   @Test
   public void testDatePointFieldRangeFacet() throws Exception {
-    doTestDatePointFieldRangeFacet("number_p_dt_dv", "number_p_dt");
+    String docValuesField = "number_p_dt_dv";
+    String nonDocValuesField = "number_p_dt";
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    int numBuckets = numValues / 2;
+    List<Long> values, sortedValues;
+    long min, max;
+    DateGapCeiling gap;
+    do {
+      values = getRandomLongs(numValues, false, MAX_DATE_EPOCH_MILLIS);
+      sortedValues = values.stream().sorted().collect(Collectors.toList());
+      min = sortedValues.get(0);
+      max = sortedValues.get(sortedValues.size() - 1);
+    } while (max > MAX_DATE_EPOCH_MILLIS || min <= MIN_DATE_EPOCH_MILLIS);
+    long initialGap = BigInteger.valueOf(max).subtract(BigInteger.valueOf(min))
+        .divide(BigInteger.valueOf(numBuckets)).longValueExact();
+    gap = new DateGapCeiling(BigInteger.valueOf(max + initialGap).subtract(BigInteger.valueOf(min)) // padding for rounding
+        .divide(BigInteger.valueOf(numBuckets)).longValueExact());
+    int[] bucketCount = new int[numBuckets];
+    int bucketNum = 0;
+    long minBucketVal = min;
+    // System.err.println("min:" + Instant.ofEpochMilli(min) + "   max: " + Instant.ofEpochMilli(max) + "   gap: " + gap);
+    // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + Instant.ofEpochMilli(minBucketVal));
+    for (long value : sortedValues) {
+      // System.err.println("value: " + Instant.ofEpochMilli(value));
+      while (value >= gap.addTo(minBucketVal)) {
+        ++bucketNum;
+        minBucketVal = gap.addTo(minBucketVal);
+        // System.err.println("bucketNum: " + bucketNum + "   minBucketVal: " + Instant.ofEpochMilli(minBucketVal));
+      }
+      ++bucketCount[bucketNum];
+    }
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertU(adoc("id", String.valueOf(i), docValuesField, Instant.ofEpochMilli(values.get(i)).toString(),
+          nonDocValuesField, Instant.ofEpochMilli(values.get(i)).toString()));
+    }
+    assertU(commit());
+
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
+    String[] testStrings = new String[numBuckets + 1];
+    testStrings[numBuckets] = "//*[@numFound='" + numValues + "']";
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField
+          + "']/lst[@name='counts']/int[@name='" + Instant.ofEpochMilli(minBucketVal).toString() 
+          + "'][.='" + bucketCount[i] + "']";
+      minBucketVal = gap.addTo(minBucketVal);
+    }
+    long maxPlusGap = gap.addTo(max);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, 
+        "facet.range.start", Instant.ofEpochMilli(min).toString(),
+        "facet.range.end", Instant.ofEpochMilli(maxPlusGap).toString(),
+        "facet.range.gap", gap.toString()),
+        testStrings);
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, 
+        "facet.range.start", Instant.ofEpochMilli(min).toString(),
+        "facet.range.end", Instant.ofEpochMilli(maxPlusGap).toString(),   
+        "facet.range.gap", gap.toString(), 
+        "facet.range.method", "dv"),
+        testStrings);
+
+    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
+    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
+    minBucketVal = min;
+    for (int i = 0 ; i < numBuckets ; ++i) {
+      testStrings[i] = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField
+          + "']/lst[@name='counts']/int[@name='" + Instant.ofEpochMilli(minBucketVal).toString() 
+          + "'][.='" + bucketCount[i] + "']";
+      minBucketVal = gap.addTo(minBucketVal);
+    }
+    maxPlusGap = gap.addTo(max);
+    // Range Faceting with method = filter should work
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, 
+        "facet.range.start", Instant.ofEpochMilli(min).toString(),
+        "facet.range.end", Instant.ofEpochMilli(maxPlusGap).toString(), 
+        "facet.range.gap", gap.toString(), 
+        "facet.range.method", "filter"),
+        testStrings);
+    // this should actually use filter method instead of dv
+    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, 
+        "facet.range.start", Instant.ofEpochMilli(min).toString(),
+        "facet.range.end", Instant.ofEpochMilli(maxPlusGap).toString(), 
+        "facet.range.gap", gap.toString(), 
+        "facet.range.method", "dv"),
+        testStrings);
   }
 
   @Test
@@ -1053,27 +1646,31 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDatePointFieldMultiValuedExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_dt_mv", getSequentialStringArrayWithDates(20));
-    testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv_dv", getSequentialStringArrayWithDates(20));
+    String[] dates = toStringArray(getRandomInstants(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_dt_mv", dates);
+    testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv_dv", dates);
   }
 
   @Test
   public void testDatePointFieldMultiValuedNonSearchableExactQuery() throws Exception {
-    testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv", getSequentialStringArrayWithDates(20), false);
-    testPointFieldMultiValuedExactQuery("number_p_dt_ni_ns_mv", getSequentialStringArrayWithDates(20), false);
+    String[] dates = toStringArray(getRandomInstants(20, false));
+    testPointFieldMultiValuedExactQuery("number_p_dt_ni_mv", dates, false);
+    testPointFieldMultiValuedExactQuery("number_p_dt_ni_ns_mv", dates, false);
   }
   
   @Test
   public void testDatePointFieldMultiValuedReturn() throws Exception {
-    testPointFieldMultiValuedReturn("number_p_dt_mv", "date", getSequentialStringArrayWithDates(20));
-    testPointFieldMultiValuedReturn("number_p_dt_ni_mv_dv", "date", getSequentialStringArrayWithDates(20));
-    testPointFieldMultiValuedReturn("number_p_dt_dv_ns_mv", "date", getSequentialStringArrayWithDates(20));
+    String[] dates = toStringArray(getRandomInstants(20, false));
+    testPointFieldMultiValuedReturn("number_p_dt_mv", "date", dates);
+    testPointFieldMultiValuedReturn("number_p_dt_ni_mv_dv", "date", dates);
+    testPointFieldMultiValuedReturn("number_p_dt_dv_ns_mv", "date", dates);
   }
 
   @Test
   public void testDatePointFieldMultiValuedRangeQuery() throws Exception {
-    testPointFieldMultiValuedRangeQuery("number_p_dt_mv", "date", getSequentialStringArrayWithDates(20));
-    testPointFieldMultiValuedRangeQuery("number_p_dt_ni_mv_dv", "date", getSequentialStringArrayWithDates(20));
+    String[] dates = toStringArray(getRandomInstants(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointFieldMultiValuedRangeQuery("number_p_dt_mv", "date", dates);
+    testPointFieldMultiValuedRangeQuery("number_p_dt_ni_mv_dv", "date", dates);
   }
 
   @Test
@@ -1089,7 +1686,8 @@ public class TestPointFields extends SolrTestCaseJ4 {
 
   @Test
   public void testDatePointMultiValuedFunctionQuery() throws Exception {
-    testPointMultiValuedFunctionQuery("number_p_dt_mv", "number_p_dt_mv_dv", "date", getSequentialStringArrayWithDates(20));
+    String[] dates = toStringArray(getRandomInstants(20, false).stream().sorted().collect(Collectors.toList()));
+    testPointMultiValuedFunctionQuery("number_p_dt_mv", "number_p_dt_mv_dv", "date", dates);
   }
 
   @Test
@@ -1097,9 +1695,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
     if (!Boolean.getBoolean("enable.update.log")) {
       return;
     }
-    testDatePointFieldsAtomicUpdates("number_p_dt", "date");
-    testDatePointFieldsAtomicUpdates("number_p_dt_dv", "date");
-    testDatePointFieldsAtomicUpdates("number_p_dt_dv_ns", "date");
+    testDatePointFieldsAtomicUpdates("number_p_dt");
+    testDatePointFieldsAtomicUpdates("number_p_dt_dv");
+    testDatePointFieldsAtomicUpdates("number_p_dt_dv_ns");
   }
 
   @Test
@@ -1107,9 +1705,9 @@ public class TestPointFields extends SolrTestCaseJ4 {
     if (!Boolean.getBoolean("enable.update.log")) {
       return;
     }
-    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_mv", "date");
-    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_ni_mv_dv", "date");
-    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_dv_ns_mv", "date");
+    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_mv");
+    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_ni_mv_dv");
+    testMultiValuedDatePointFieldsAtomicUpdates("number_p_dt_dv_ns_mv");
   }
 
   @Test
@@ -1122,45 +1720,59 @@ public class TestPointFields extends SolrTestCaseJ4 {
   
   @Test
   public void testDatePointFieldNotIndexed() throws Exception {
-    doTestFieldNotIndexed("number_p_dt_ni", getSequentialStringArrayWithDates(10));
-    doTestFieldNotIndexed("number_p_dt_ni_mv", getSequentialStringArrayWithDates(10));
+    String[] dates = toStringArray(getRandomInstants(10, false));
+    doTestFieldNotIndexed("number_p_dt_ni", dates);
+    doTestFieldNotIndexed("number_p_dt_ni_mv", dates);
   }
   
   @Test
   public void testIndexOrDocValuesQuery() throws Exception {
-    String[] fieldTypeNames = new String[]{"_p_i", "_p_l", "_p_d", "_p_f"};
-    FieldType[] fieldTypes = new FieldType[]{new IntPointField(), new LongPointField(), new DoublePointField(), new FloatPointField()};
-    assert fieldTypeNames.length == fieldTypes.length;
+    String[] fieldTypeNames = new String[] { "_p_i", "_p_l", "_p_d", "_p_f", "_p_dt" };
+    FieldType[] fieldTypes = new FieldType[]
+        { new IntPointField(), new LongPointField(), new DoublePointField(), new FloatPointField(), new DatePointField() };
+    String[] ints = toStringArray(getRandomInts(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] longs = toStringArray(getRandomLongs(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] doubles = toStringArray(getRandomDoubles(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] floats = toStringArray(getRandomFloats(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] dates = toStringArray(getRandomInstants(2, false).stream().sorted().collect(Collectors.toList()));
+    String[] min = new String[] { ints[0], longs[0], doubles[0], floats[0], dates[0] };
+    String[] max = new String[] { ints[1], longs[1], doubles[1], floats[1], dates[1] };
+    assert fieldTypeNames.length == fieldTypes.length
+        && fieldTypeNames.length == max.length
+        && fieldTypeNames.length == min.length;
     for (int i = 0; i < fieldTypeNames.length; i++) {
       SchemaField fieldIndexed = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i]);
       SchemaField fieldIndexedAndDv = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i] + "_dv");
       SchemaField fieldIndexedMv = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i] + "_mv");
       SchemaField fieldIndexedAndDvMv = h.getCore().getLatestSchema().getField("foo_" + fieldTypeNames[i] + "_mv_dv");
-      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexed, "0", "10", true, true) instanceof PointRangeQuery);
-      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDv, "0", "10", true, true) instanceof IndexOrDocValuesQuery);
-      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedMv, "0", "10", true, true) instanceof PointRangeQuery);
-      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDvMv, "0", "10", true, true) instanceof IndexOrDocValuesQuery);
-      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexed, "0") instanceof PointRangeQuery);
-      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDv, "0") instanceof IndexOrDocValuesQuery);
-      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedMv, "0") instanceof PointRangeQuery);
-      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDvMv, "0") instanceof IndexOrDocValuesQuery);
+      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexed, min[i], max[i], true, true) instanceof PointRangeQuery);
+      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDv, min[i], max[i], true, true) instanceof IndexOrDocValuesQuery);
+      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedMv, min[i], max[i], true, true) instanceof PointRangeQuery);
+      assertTrue(fieldTypes[i].getRangeQuery(null, fieldIndexedAndDvMv, min[i], max[i], true, true) instanceof IndexOrDocValuesQuery);
+      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexed, min[i]) instanceof PointRangeQuery);
+      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDv, min[i]) instanceof IndexOrDocValuesQuery);
+      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedMv, min[i]) instanceof PointRangeQuery);
+      assertTrue(fieldTypes[i].getFieldQuery(null, fieldIndexedAndDvMv, min[i]) instanceof IndexOrDocValuesQuery);
     }
   }
   
   public void testInternals() throws IOException {
-    String[] types = new String[]{"i", "l", "f", "d"};
+    String[] types = new String[]{"i", "l", "f", "d", "dt"};
+    String[][] values = new String[][] {
+        toStringArray(getRandomInts(10, false)),
+        toStringArray(getRandomLongs(10, false)),
+        toStringArray(getRandomFloats(10, false)),
+        toStringArray(getRandomDoubles(10, false)),
+        toStringArray(getRandomInstants(10, false))
+    };
+    assertEquals(types.length, values.length);
     Set<String> typesTested = new HashSet<>();
-    for (String type:types) {
+    for (int i = 0 ; i < types.length ; ++i) {
       for (String suffix:FIELD_SUFFIXES) {
-        doTestInternals("number_p_" + type + suffix, getSequentialStringArrayWithInts(10));
-        typesTested.add("*_p_" + type + suffix);
+        doTestInternals("number_p_" + types[i] + suffix, values[i]);
+        typesTested.add("*_p_" + types[i] + suffix);
       }
     }
-    for (String suffix:FIELD_SUFFIXES) {
-      doTestInternals("number_p_dt" + suffix, getSequentialStringArrayWithDates(10));
-      typesTested.add("*_p_dt" + suffix);
-    }
-
     assertEquals("Missing types in the test", dynFieldRegexesForType(PointField.class), typesTested);
   }
   
@@ -1197,24 +1809,43 @@ public class TestPointFields extends SolrTestCaseJ4 {
   }
 
   private List<Double> getRandomDoubles(int length, boolean missingVals) {
-    return getRandomList(length, missingVals, 
-        () -> random().nextDouble() * Double.MAX_VALUE * (random().nextBoolean() ? 1.D : -1.D));
+    return getRandomList(length, missingVals, () -> {
+      Double d = Double.NaN; 
+      while (d.isNaN()) {
+        d = Double.longBitsToDouble(random().nextLong());
+      }
+      return d; 
+    });
   }
 
   private List<Float> getRandomFloats(int length, boolean missingVals) {
-    return getRandomList(length, missingVals,
-        () -> random().nextFloat() * Float.MAX_VALUE * (random().nextBoolean() ? 1.f : -1.f));
+    return getRandomList(length, missingVals, () -> {
+      Float f = Float.NaN;
+      while (f.isNaN()) {
+        f = Float.intBitsToFloat(random().nextInt());
+      }
+      return f;
+    });
+  }
+
+  private List<Integer> getRandomInts(int length, boolean missingVals, int bound) {
+    return getRandomList(length, missingVals, () -> random().nextInt() % bound);
   }
 
   private List<Integer> getRandomInts(int length, boolean missingVals) {
     return getRandomList(length, missingVals, () -> random().nextInt());
   }
 
-  private List<Long> getRandomLongs(int length, boolean missingVals){
+  private List<Long> getRandomLongs(int length, boolean missingVals, long bound) {
+    assert bound > 0L;
+    return getRandomList(length, missingVals, () -> random().nextLong() % bound); // see Random.nextInt(int bound)
+  }
+
+  private List<Long> getRandomLongs(int length, boolean missingVals) {
     return getRandomList(length, missingVals, () -> random().nextLong());
   }
 
-  private List<Instant> getRandomInstants(int length, boolean missingVals){
+  private List<Instant> getRandomInstants(int length, boolean missingVals) {
     return getRandomList(length, missingVals, () -> Instant.ofEpochMilli(random().nextLong()));
   }
   
@@ -1272,47 +1903,46 @@ public class TestPointFields extends SolrTestCaseJ4 {
     doTestIntPointFieldExactQuery(field, testLong, true);
   }
 
+  private String getTestString(boolean searchable, int numFound) {
+    return "//*[@numFound='" + (searchable ? Integer.toString(numFound) : "0") + "']";
+  }
+  
   /**
    * @param field the field to use for indexing and searching against
    * @param testLong set to true if "field" is expected to support long values, false if only integers
    * @param searchable set to true if searches against "field" should succeed, false if field is only stored and searches should always get numFound=0
    */
   private void doTestIntPointFieldExactQuery(final String field, final boolean testLong, final boolean searchable) throws Exception {
-    final String MATCH_ONE = "//*[@numFound='" + (searchable ? "1" : "0") + "']";
-    final String MATCH_TWO = "//*[@numFound='" + (searchable ? "2" : "0") + "']";
-
-    for (int i=0; i < 10; i++) {
-      assertU(adoc("id", String.valueOf(i), field, String.valueOf(i+1)));
+    int numValues = 10 * RANDOM_MULTIPLIER;
+    Map<String,Integer> randCount = new HashMap<>(numValues);
+    String[] rand = testLong ? toStringArray(getRandomLongs(numValues, false))
+                             : toStringArray(getRandomInts(numValues, false));
+    for (int i = 0 ; i < numValues ; i++) {
+      randCount.merge(rand[i], 1, (a, b) -> a + b); // count unique values
+      assertU(adoc("id", String.valueOf(i), field, rand[i]));
     }
     assertU(commit());
-    for (int i = 0; i < 10; i++) {
-      assertQ(req("q", field + ":"+(i+1), "fl", "id, " + field), 
-          MATCH_ONE);
+
+    for (int i = 0 ; i < numValues ; i++) {
+      assertQ(req("q", field + ":" + (rand[i].startsWith("-") ? "\\" : "") + rand[i],
+          "fl", "id," + field), getTestString(searchable, randCount.get(rand[i])));
     }
     
-    for (int i = 0; i < 10; i++) {
-      assertQ(req("debug", "true", "q", field + ":" + (i+1) + " OR " + field + ":" + ((i+1)%10 + 1)), MATCH_TWO);
+    StringBuilder builder = new StringBuilder();
+    for (String value : randCount.keySet()) {
+      if (builder.length() != 0) {
+        builder.append(" OR ");
+      }
+      if (value.startsWith("-")) {
+        builder.append("\\"); // escape negative sign
+      }
+      builder.append(value);
     }
+    assertQ(req("debug", "true", "q", field + ":(" + builder.toString() + ")"), getTestString(searchable, numValues));
     
     assertU(adoc("id", String.valueOf(Integer.MAX_VALUE), field, String.valueOf(Integer.MAX_VALUE)));
     assertU(commit());
-    assertQ(req("q", field + ":"+Integer.MAX_VALUE, "fl", "id, " + field), 
-        MATCH_ONE);
-    
-    if (testLong) {
-      for (long i = (long)Integer.MAX_VALUE; i < (long)Integer.MAX_VALUE + 10; i++) {
-        assertU(adoc("id", String.valueOf(i), field, String.valueOf(i+1)));
-      }
-      assertU(commit());
-      for (long i = (long)Integer.MAX_VALUE; i < (long)Integer.MAX_VALUE + 10; i++) {
-        assertQ(req("q", field + ":"+(i+1), "fl", "id, " + field), 
-                MATCH_ONE);
-      }
-      assertU(adoc("id", String.valueOf(Long.MAX_VALUE), field, String.valueOf(Long.MAX_VALUE)));
-      assertU(commit());
-      assertQ(req("q", field + ":"+Long.MAX_VALUE, "fl", "id, " + field), 
-              MATCH_ONE);
-    }
+    assertQ(req("q", field + ":"+Integer.MAX_VALUE, "fl", "id, " + field), getTestString(searchable, 1));
     
     clearIndex();
     assertU(commit());
@@ -1489,54 +2119,6 @@ public class TestPointFields extends SolrTestCaseJ4 {
         SolrException.ErrorCode.BAD_REQUEST);
   }
   
-  private void doTestIntPointFieldRangeFacet(String docValuesField, String nonDocValuesField) throws Exception {
-    for (int i = 0; i < 10; i++) {
-      assertU(adoc("id", String.valueOf(i), docValuesField, String.valueOf(i), nonDocValuesField, String.valueOf(i)));
-    }
-    assertU(commit());
-    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).hasDocValues());
-    assertTrue(h.getCore().getLatestSchema().getField(docValuesField).getType() instanceof PointField);
-    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2"), 
-        "//*[@numFound='10']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
-    
-    assertQ(req("q", "*:*", "facet", "true", "facet.range", docValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "dv"), 
-        "//*[@numFound='10']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + docValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
-    
-    assertFalse(h.getCore().getLatestSchema().getField(nonDocValuesField).hasDocValues());
-    assertTrue(h.getCore().getLatestSchema().getField(nonDocValuesField).getType() instanceof PointField);
-    // Range Faceting with method = filter should work
-    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "filter"), 
-        "//*[@numFound='10']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
-    
-    // this should actually use filter method instead of dv
-    assertQ(req("q", "*:*", "facet", "true", "facet.range", nonDocValuesField, "facet.range.start", "-10", "facet.range.end", "10", "facet.range.gap", "2", "facet.range.method", "dv"), 
-        "//*[@numFound='10']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='0'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='2'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='4'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='6'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='8'][.='2']",
-        "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='" + nonDocValuesField + "']/lst[@name='counts']/int[@name='-10'][.='0']");
-  }
-
   private void doTestIntPointFunctionQuery(String field, String type) throws Exception {
     for (int i = 9; i >= 0; i--) {
       assertU(adoc("id", String.valueOf(i), field, String.valueOf(i)));
@@ -1600,7 +2182,7 @@ public class TestPointFields extends SolrTestCaseJ4 {
   }
 
   
-  private void testPointStats(String field, String dvField, String[] numbers, double min, double max, String count, String missing, double delta) {
+  private void testPointStats(String field, String dvField, String[] numbers, double min, double max, int count, int missing, double delta) {
     String minMin = String.valueOf(min - Math.abs(delta*min));
     String maxMin = String.valueOf(min + Math.abs(delta*min));
     String minMax = String.valueOf(max - Math.abs(delta*max));
@@ -1614,10 +2196,10 @@ public class TestPointFields extends SolrTestCaseJ4 {
     assertTrue(h.getCore().getLatestSchema().getField(dvField).getType() instanceof PointField);
     assertQ(req("q", "*:*", "fl", "id, " + dvField, "stats", "true", "stats.field", dvField), 
         "//*[@numFound='11']",
-        "//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/double[@name='min'][.>='" + minMin + "']",
-        "//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/double[@name='min'][.<='" + maxMin+ "']",
-        "//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dvField+ "']/double[@name='max'][.>='" + minMax + "']",
-        "//lst[@name='stats']/lst[@name='stats_fields']/lst[@name='" + dv

<TRUNCATED>

[4/6] lucene-solr:branch_7x: SOLR-10796: TestPointFields: increase randomized testing of non-trivial values

Posted by sa...@apache.org.
SOLR-10796: TestPointFields: increase randomized testing of non-trivial values


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/83400bd8
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/83400bd8
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/83400bd8

Branch: refs/heads/branch_7x
Commit: 83400bd81eb911ee3623c6636f1c6e968cb0c46d
Parents: 95d4a7f
Author: Steve Rowe <sa...@apache.org>
Authored: Mon Jul 10 19:58:23 2017 -0400
Committer: Steve Rowe <sa...@apache.org>
Committed: Mon Jul 10 19:59:15 2017 -0400

----------------------------------------------------------------------
 solr/CHANGES.txt                                |    2 +
 .../org/apache/solr/schema/TestPointFields.java | 1400 ++++++++++++------
 2 files changed, 938 insertions(+), 464 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/83400bd8/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index b8031c7..29ab3c0 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -467,6 +467,8 @@ Other Changes
 
 * SOLR-10898: Fix SOLR-10898 to not deterministicly fail 1/512 runs (hossman)
 
+* SOLR-10796: TestPointFields: increase randomized testing of non-trivial values.  (Steve Rowe)
+
 ==================  6.7.0 ==================
 
 Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release.


[6/6] lucene-solr:branch_7_0: SOLR-10796: TestPointFields: increase randomized testing of non-trivial values

Posted by sa...@apache.org.
SOLR-10796: TestPointFields: increase randomized testing of non-trivial values


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/0511aeb5
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/0511aeb5
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/0511aeb5

Branch: refs/heads/branch_7_0
Commit: 0511aeb5137c81cf4966f691d27b8c74bda04e20
Parents: fd0e520
Author: Steve Rowe <sa...@apache.org>
Authored: Mon Jul 10 19:58:23 2017 -0400
Committer: Steve Rowe <sa...@apache.org>
Committed: Mon Jul 10 19:59:47 2017 -0400

----------------------------------------------------------------------
 solr/CHANGES.txt                                |    2 +
 .../org/apache/solr/schema/TestPointFields.java | 1400 ++++++++++++------
 2 files changed, 938 insertions(+), 464 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0511aeb5/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 38b761c..5f98896 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -418,6 +418,8 @@ Other Changes
 
 * SOLR-10898: Fix SOLR-10898 to not deterministicly fail 1/512 runs (hossman)
 
+* SOLR-10796: TestPointFields: increase randomized testing of non-trivial values.  (Steve Rowe)
+
 ==================  6.7.0 ==================
 
 Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release.