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

[02/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/FunctionTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/FunctionTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/FunctionTest.java
new file mode 100644
index 0000000..dac7921
--- /dev/null
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/FunctionTest.java
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.expression;
+
+
+import org.apache.solr.analytics.AbstractAnalyticsStatsTest;
+import org.apache.solr.analytics.facet.AbstractAnalyticsFacetTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class FunctionTest extends AbstractAnalyticsStatsTest {
+  static String fileName = "functions.txt";
+
+  static public final int INT = 71;
+  static public final int LONG = 36;
+  static public final int FLOAT = 93;
+  static public final int DOUBLE = 49;
+  static public final int DATE = 12;
+  static public final int STRING = 28;
+  static public final int NUM_LOOPS = 100;
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    initCore("solrconfig-analytics.xml","schema-analytics.xml");
+    h.update("<delete><query>*:*</query></delete>");
+    
+    for (int j = 0; j < NUM_LOOPS; ++j) {
+      int i = j%INT+1;
+      long l = j%LONG+1;
+      float f = j%FLOAT+1;
+      double d = j%DOUBLE+1;
+      double d0 = j%DOUBLE;
+      String dt = (1800+j%DATE) + "-06-30T23:59:59Z";
+      String s = "str" + (j%STRING);
+
+      double add_if = (double)i+f;
+      double add_ldf = (double)l+d+f;
+      double mult_if = (double)i*f;
+      double mult_ldf = (double)l*d*f;
+      double div_if = (double)i/f;
+      double div_ld = (double)l/d;
+      double pow_if = Math.pow(i,f);
+      double pow_ld = Math.pow(l,d);
+      int neg_i = i*-1;
+      long neg_l = l*-1;
+      String dm_2y = (1802+j%DATE) + "-06-30T23:59:59Z";
+      String dm_2m = (1800+j%DATE) + "-08-30T23:59:59Z";
+      String concat_first = "this is the first"+s;
+      String concat_second = "this is the second"+s;
+      
+      assertU(adoc(AbstractAnalyticsFacetTest.filter("id", "1000" + j, "int_id", "" + i, "long_ld", "" + l, "float_fd", "" + f, 
+            "double_dd", "" + d,  "date_dtd", dt, "string_sd", s,
+            "add_if_dd", ""+add_if, "add_ldf_dd", ""+add_ldf, "mult_if_dd", ""+mult_if, "mult_ldf_dd", ""+mult_ldf,
+            "div_if_dd", ""+div_if, "div_ld_dd", ""+div_ld, "pow_if_dd", ""+pow_if, "pow_ld_dd", ""+pow_ld,
+            "neg_id", ""+neg_i, "neg_ld", ""+neg_l, "const_8_dd", "8", "const_10_dd", "10", "dm_2y_dtd", dm_2y, "dm_2m_dtd", dm_2m,
+            "const_00_dtd", "1800-06-30T23:59:59Z", "const_04_dtd", "1804-06-30T23:59:59Z", "const_first_sd", "this is the first", "const_second_sd", "this is the second",
+            "concat_first_sd", concat_first, "concat_second_sd", concat_second, "miss_dd", ""+d0 )));
+      
+      
+      if (usually()) {
+        assertU(commit()); // to have several segments
+      }
+    }
+    
+    assertU(commit()); 
+    
+    setResponse(h.query(request(fileToStringArr(FunctionTest.class, fileName))));
+  }
+      
+  @Test
+  public void addTest() throws Exception { 
+    double result = (Double)getStatResult("ar", "sum", VAL_TYPE.DOUBLE);
+    double calculated = (Double)getStatResult("ar", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+    // TODO checfk why asserted 2times
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+
+    result = (Double)getStatResult("ar", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("ar", "meanc", VAL_TYPE.DOUBLE);
+    assertTrue(result==calculated);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+  }
+  
+  @Test
+  public void multiplyTest() throws Exception { 
+    double result = (Double)getStatResult("mr", "sum", VAL_TYPE.DOUBLE);
+    double calculated = (Double)getStatResult("mr", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+    
+    result = (Double)getStatResult("mr", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("mr", "meanc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+  }
+  
+  @Test
+  public void divideTest() throws Exception { 
+    Double result = (Double)getStatResult("dr", "sum", VAL_TYPE.DOUBLE);
+    Double calculated = (Double)getStatResult("dr", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+    
+    result = (Double)getStatResult("dr", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("dr", "meanc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+  }
+  
+  @Test
+  public void powerTest() throws Exception { 
+    double result = (Double)getStatResult("pr", "sum", VAL_TYPE.DOUBLE);
+    double calculated = (Double)getStatResult("pr", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+    
+    result = (Double)getStatResult("pr", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("pr", "meanc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+  }
+  
+  @Test
+  public void negateTest() throws Exception { 
+    double result = (Double)getStatResult("nr", "sum", VAL_TYPE.DOUBLE);
+    double calculated = (Double)getStatResult("nr", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+    
+    result = (Double)getStatResult("nr", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("nr", "meanc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+  }
+
+  @Test 
+  public void absoluteValueTest() throws Exception {
+    double result = (Double)getStatResult("avr", "sum", VAL_TYPE.DOUBLE);
+    double calculated = (Double)getStatResult("avr", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+    
+    result = (Double)getStatResult("avr", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("avr", "meanc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+  }
+  
+  @Test
+  public void constantNumberTest() throws Exception { 
+    double result = (Double)getStatResult("cnr", "sum", VAL_TYPE.DOUBLE);
+    double calculated = (Double)getStatResult("cnr", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+    
+    result = (Double)getStatResult("cnr", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("cnr", "meanc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+  }
+  
+  @Test
+  public void dateMathTest() throws Exception {
+    String result = (String)getStatResult("dmr", "median", VAL_TYPE.DATE);
+    String calculated = (String)getStatResult("dmr", "medianc", VAL_TYPE.DATE);
+    assertEquals(getRawResponse(), result, calculated);
+    
+    result = (String)getStatResult("dmr", "max", VAL_TYPE.DATE);
+    calculated = (String)getStatResult("dmr", "maxc", VAL_TYPE.DATE);
+    assertEquals(getRawResponse(), result, calculated);
+  }
+  
+  @Test
+  public void constantDateTest() throws Exception { 
+    String result = (String)getStatResult("cdr", "median", VAL_TYPE.DATE);
+    String calculated = (String)getStatResult("cdr", "medianc", VAL_TYPE.DATE);
+    assertEquals(getRawResponse(), result, calculated);
+    assertEquals(getRawResponse(), result, calculated);
+    
+    result = (String)getStatResult("cdr", "max", VAL_TYPE.DATE);
+    calculated = (String)getStatResult("cdr", "maxc", VAL_TYPE.DATE);
+    assertEquals(getRawResponse(), result, calculated);
+  }
+  
+  @Test
+  public void constantStringTest() throws Exception { 
+    String result = (String)getStatResult("csr", "min", VAL_TYPE.STRING);
+    String calculated = (String)getStatResult("csr", "minc", VAL_TYPE.STRING);
+    assertEquals(getRawResponse(), result, calculated);
+    
+    result = (String)getStatResult("csr", "max", VAL_TYPE.STRING);
+    calculated = (String)getStatResult("csr", "maxc", VAL_TYPE.STRING);
+    assertEquals(getRawResponse(), result, calculated);
+  }
+  
+  @Test
+  public void concatenateTest() throws Exception { 
+    String result = (String)getStatResult("cr", "min", VAL_TYPE.STRING);
+    String calculated = (String)getStatResult("cr", "minc", VAL_TYPE.STRING);
+    assertEquals(getRawResponse(), result, calculated);
+    
+    result = (String)getStatResult("cr", "max", VAL_TYPE.STRING);
+    calculated = (String)getStatResult("cr", "maxc", VAL_TYPE.STRING);
+    assertEquals(getRawResponse(), result, calculated);
+  }
+  
+  @Test
+  public void missingTest() throws Exception { 
+    double min = (Double)getStatResult("ms", "min", VAL_TYPE.DOUBLE);
+    double max = (Double)getStatResult("ms", "max", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(), 48.0d, max, 0.0);
+    assertEquals(getRawResponse(), 1.0d, min, 0.0);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetCloudTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetCloudTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetCloudTest.java
new file mode 100644
index 0000000..99e5103
--- /dev/null
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetCloudTest.java
@@ -0,0 +1,284 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Scanner;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.lucene.util.IOUtils;
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
+import org.apache.solr.analytics.util.MedianCalculator;
+import org.apache.solr.analytics.util.OrdinalCalculator;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.cloud.AbstractDistribZkTestBase;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.NamedList;
+import org.junit.AfterClass;
+
+public class AbstractAnalyticsFacetCloudTest extends SolrCloudTestCase {
+  protected static final HashMap<String,Object> defaults = new HashMap<>();
+  
+  protected static final String COLLECTIONORALIAS = "collection1";
+  protected static final int TIMEOUT = DEFAULT_TIMEOUT;
+  protected static final String id = "id";
+
+  public static void setupCluster() throws Exception {
+    configureCluster(2)
+        .addConfig("conf", configset("cloud-analytics"))
+        .configure();
+
+    CollectionAdminRequest.createCollection(COLLECTIONORALIAS, "conf", 2, 1).process(cluster.getSolrClient());
+    AbstractDistribZkTestBase.waitForRecoveriesToFinish(COLLECTIONORALIAS, cluster.getSolrClient().getZkStateReader(),
+        false, true, TIMEOUT);
+    
+    cleanIndex();
+  }
+
+  public static void cleanIndex() throws Exception {
+    new UpdateRequest()
+        .deleteByQuery("*:*")
+        .commit(cluster.getSolrClient(), COLLECTIONORALIAS);
+  }
+  
+  protected String latestType = "";
+  
+  @AfterClass
+  public static void afterClassAbstractAnalysis() {
+    defaults.clear();
+  }
+
+  protected NamedList<Object> queryCloudAnalytics(String[] testParams) throws SolrServerException, IOException, InterruptedException {
+    ModifiableSolrParams params = new ModifiableSolrParams();
+    params.set("q", "*:*");
+    params.set("indent", "true");
+    params.set("olap", "true");
+    params.set("rows", "0");
+    for (int i = 0; i + 1 < testParams.length;) {
+      params.add(testParams[i++], testParams[i++]);
+    }
+    cluster.waitForAllNodes(10000);
+    QueryRequest qreq = new QueryRequest(params);
+    QueryResponse resp = qreq.process(cluster.getSolrClient(), COLLECTIONORALIAS);
+    return resp.getResponse();
+  }
+  
+  @SuppressWarnings("unchecked")
+  protected <T> ArrayList<T> getValueList(NamedList<Object> response, String infoName, String facetType, String facetName, String exprName, boolean includeMissing) {
+    NamedList<NamedList<Object>> facetList = 
+        (NamedList<NamedList<Object>>)response.findRecursive(AnalyticsResponseHeadings.COMPLETED_OLD_HEADER,
+                                                             infoName,
+                                                             facetType,
+                                                             facetName);
+    
+    ArrayList<T> results = new ArrayList<>();
+    facetList.forEach( (name, expressions) -> {
+      if (!includeMissing && !name.equals("(MISSING)")) {
+        T result = (T)expressions.get(exprName);
+        if (result != null)
+          results.add(result);
+      }
+    });
+    return results;
+  }
+  
+  protected boolean responseContainsFacetValue(NamedList<Object> response, String infoName, String facetType, String facetName, String facetValue) {
+    return null != response.findRecursive(AnalyticsResponseHeadings.COMPLETED_OLD_HEADER,
+                                          infoName,
+                                          facetType,
+                                          facetName,
+                                          facetValue);
+  }
+
+
+  public static void increment(List<Long> list, int idx){
+    Long i = list.remove(idx);
+    list.add(idx, i+1);
+  }
+  
+  public static String[] filter(String...args){
+    List<String> l = new ArrayList<>();
+    for( int i=0; i <args.length; i+=2){
+      if( args[i+1].equals("0") || args[i+1].equals("0.0") || 
+          args[i+1].equals("1800-12-31T23:59:59Z") || args[i+1].equals("str0") ||
+          args[i+1].equals("this is the firststr0") || 
+          args[i+1].equals("this is the secondstr0") ){
+        continue;
+      }
+      l.add(args[i]);
+      l.add(args[i+1]);
+    }
+    return l.toArray(new String[0]);
+  }
+  
+  protected void setLatestType(String latestType) {
+    this.latestType = latestType;
+  }
+
+  @SuppressWarnings({ "unchecked", "rawtypes" })
+  public <T extends Number & Comparable<T>> ArrayList calculateNumberStat(ArrayList<ArrayList<T>> lists, String stat) {
+    ArrayList result;
+    if (stat.equals("median")) {
+      result = new ArrayList<Double>();
+      for (List<T> list : lists) {
+        result.add(MedianCalculator.getMedian(list));
+      }
+    } else if (stat.equals("mean")) {
+      result = new ArrayList<Double>();
+      for (List<T> list : lists) {
+        double d = 0;
+        for (T element : list) {
+          d += element.doubleValue();
+        }
+        result.add(d/list.size());
+      }
+    } else if (stat.equals("sum")) {
+      result = new ArrayList<Double>();
+      for (Collection<T> list : lists) {
+        double d = 0;
+        for (T element : list) {
+          d += element.doubleValue();
+        }
+        result.add(d);
+      }
+    } else if (stat.equals("sumOfSquares")) {
+      result = new ArrayList<Double>();
+      for (List<T> list : lists) {
+        double d = 0;
+        for (T element : list) {
+          d += element.doubleValue()*element.doubleValue();
+        }
+        result.add(d);
+      }
+    } else if (stat.equals("stddev")) {
+      result = new ArrayList<Double>();
+      for (List<T> list : lists) {
+        double sum = 0;
+        double sumSquares = 0;
+        for (T element : list) {
+          sum += element.doubleValue();
+          sumSquares += element.doubleValue()*element.doubleValue();
+        }
+        String res = Double.toString(Math.sqrt(sumSquares/list.size()-sum*sum/(list.size()*list.size())));
+        result.add(Double.parseDouble(res));
+      }
+    } else {
+      throw new IllegalArgumentException();
+    }
+    return result;
+  }
+
+  @SuppressWarnings({ "unchecked", "rawtypes" })
+  public <T extends Comparable<T>> ArrayList calculateStat(ArrayList<ArrayList<T>> lists, String stat) {
+    ArrayList result;
+    if (stat.contains("perc_")) {
+      result = new ArrayList<T>();
+      for (List<T> list : lists) {
+        if( list.size() == 0) continue;
+        int ord = (int) Math.ceil(Double.parseDouble(stat.substring(5))/100 * list.size()) - 1;
+        ArrayList<Integer> percs = new ArrayList<>(1);
+        percs.add(ord);
+        OrdinalCalculator.putOrdinalsInPosition(list, percs);
+        result.add(list.get(ord));
+      }
+    } else if (stat.equals("count")) {
+      result = new ArrayList<Long>();
+      for (List<T> list : lists) {
+        result.add((long)list.size());
+      }
+    } else if (stat.equals("missing")) {
+      result = new ArrayList<Long>();
+      for (ArrayList<T> list : lists) {
+        result.add(calculateMissing(list,latestType));
+      }
+    } else if (stat.equals("unique")) {
+      result = new ArrayList<Long>();
+      for (List<T> list : lists) {
+        HashSet<T> set = new HashSet<>();
+        set.addAll(list);
+        result.add((long)set.size());
+      }
+    } else if (stat.equals("max")) {
+      result = new ArrayList<T>();
+      for (List<T> list : lists) {
+        if( list.size() == 0) continue;
+        Collections.sort(list);
+        result.add(list.get(list.size()-1));
+      }
+    } else if (stat.equals("min")) {
+      result = new ArrayList<T>();
+      for (List<T> list : lists) {
+        if( list.size() == 0) continue;
+        Collections.sort((List<T>)list);
+        result.add(list.get(0));
+      }
+    } else {
+      result = null;
+    }
+    return result;
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T extends Comparable<T>> Long calculateMissing(ArrayList<T> list, String type) {
+    T def = (T)defaults.get(type);
+    long miss = 0;
+    for (T element : list) {
+      if (element.compareTo(def)==0) {
+        miss++;
+      }
+    }
+    return Long.valueOf(miss);
+  }
+
+  public static ModifiableSolrParams fileToParams(Class<?> clazz, String fileName) throws FileNotFoundException {
+    InputStream in = clazz.getResourceAsStream(fileName);
+    if (in == null) throw new FileNotFoundException("Resource not found: " + fileName);
+    Scanner file = new Scanner(in, "UTF-8");
+    try { 
+      ModifiableSolrParams params = new ModifiableSolrParams();
+      params.set("q", "*:*");
+      params.set("indent", "true");
+      params.set("olap", "true");
+      params.set("rows", "0");
+      while (file.hasNextLine()) {
+        String line = file.nextLine();
+        line = line.trim();
+        if( StringUtils.isBlank(line) || line.startsWith("#")){
+          continue;
+        }
+        String[] param = line.split("=");
+        params.set(param[0], param[1]);
+      }
+      return params;
+    } finally {
+      IOUtils.closeWhileHandlingException(file, in);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetTest.java
index 3660208..ff0e7da 100644
--- a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetTest.java
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetTest.java
@@ -31,8 +31,9 @@ import java.util.Scanner;
 
 import org.apache.lucene.util.IOUtils;
 import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
 import org.apache.solr.analytics.util.MedianCalculator;
-import org.apache.solr.analytics.util.PercentileCalculator;
+import org.apache.solr.analytics.util.OrdinalCalculator;
 import org.apache.solr.request.SolrQueryRequest;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -92,9 +93,10 @@ public class AbstractAnalyticsFacetTest extends SolrTestCaseJ4 {
   }
   private NodeList getNodes(String n1, String n2, String n3, String element, String n4) throws XPathExpressionException {
     // Construct the XPath expression. The form better not change or all these will fail.
-    StringBuilder sb = new StringBuilder("/response/lst[@name='stats']/lst[@name='").append(n1).append("']");
+    StringBuilder sb = new StringBuilder("/response/lst[@name='"+AnalyticsResponseHeadings.COMPLETED_OLD_HEADER+"']/lst[@name='").append(n1).append("']");
     sb.append("/lst[@name='").append(n2).append("']");
     sb.append("/lst[@name='").append(n3).append("']");
+    sb.append("/lst[@name!='(MISSING)']");
     sb.append("//").append(element).append("[@name='").append(n4).append("']");
     return (NodeList)xPathFact.newXPath().compile(sb.toString()).evaluate(doc, XPathConstants.NODESET);
 
@@ -229,11 +231,14 @@ public class AbstractAnalyticsFacetTest extends SolrTestCaseJ4 {
   public <T extends Comparable<T>> ArrayList calculateStat(ArrayList<ArrayList<T>> lists, String stat) {
     ArrayList result;
     if (stat.contains("perc_")) {
-      double[] perc = new double[]{Double.parseDouble(stat.substring(5))/100};
       result = new ArrayList<T>();
       for (List<T> list : lists) {
         if( list.size() == 0) continue;
-        result.add(PercentileCalculator.getPercentiles(list, perc).get(0));
+        int ord = (int) Math.ceil(Double.parseDouble(stat.substring(5))/100 * list.size()) - 1;
+        ArrayList<Integer> percs = new ArrayList<>(1);
+        percs.add(ord);
+        OrdinalCalculator.putOrdinalsInPosition(list, percs);
+        result.add(list.get(ord));
       }
     } else if (stat.equals("count")) {
       result = new ArrayList<Long>();
@@ -294,7 +299,7 @@ public class AbstractAnalyticsFacetTest extends SolrTestCaseJ4 {
 
   
   public static String[] fileToStringArr(Class<?> clazz, String fileName) throws FileNotFoundException {
-    InputStream in = clazz.getResourceAsStream(fileName);
+    InputStream in = clazz.getResourceAsStream("/solr/analytics/" + fileName);
     if (in == null) throw new FileNotFoundException("Resource not found: " + fileName);
     Scanner file = new Scanner(in, "UTF-8");
     try { 
@@ -304,7 +309,14 @@ public class AbstractAnalyticsFacetTest extends SolrTestCaseJ4 {
         if (line.length()<2) {
           continue;
         }
+        int commentStart = line.indexOf("//");
+        if (commentStart >= 0) {
+          line = line.substring(0,commentStart);
+        }
         String[] param = line.split("=");
+        if (param.length != 2) {
+          continue;
+        }
         strList.add(param[0]);
         strList.add(param[1]);
       }
@@ -313,4 +325,19 @@ public class AbstractAnalyticsFacetTest extends SolrTestCaseJ4 {
       IOUtils.closeWhileHandlingException(file, in);
     }
   }
+  
+  protected void removeNodes(String xPath, List<Double> string) throws XPathExpressionException {
+    NodeList missingNodes = getNodes(xPath);
+    List<Double> result = new ArrayList<Double>();
+    for (int idx = 0; idx < missingNodes.getLength(); ++idx) {
+      result.add(Double.parseDouble(missingNodes.item(idx).getTextContent()));
+    }
+    string.removeAll(result);
+  }
+
+  protected NodeList getNodes(String xPath) throws XPathExpressionException {
+    StringBuilder sb = new StringBuilder(xPath);
+    return (NodeList) xPathFact.newXPath().compile(sb.toString()).evaluate(doc, XPathConstants.NODESET);
+  }
+  
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FacetSortingTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FacetSortingTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FacetSortingTest.java
new file mode 100644
index 0000000..ef09014
--- /dev/null
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FacetSortingTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import org.apache.solr.analytics.AbstractAnalyticsStatsTest;
+import org.apache.solr.analytics.expression.ExpressionTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class FacetSortingTest extends AbstractAnalyticsStatsTest {
+  private static String fileName = "facetSorting.txt";
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    initCore("solrconfig-analytics.xml", "schema-analytics.xml");
+    h.update("<delete><query>*:*</query></delete>");
+
+    // The data set below is so generated that in bucket corresponding fieldFacet B, double_dd column has null values 
+    // and in bucket C corresponding to fieldFacet C has null values for column long_ld. 
+    // FieldFaceting occurs on string_sd field
+    assertU(adoc("id", "1001", "string_sd", "A", "double_dd", "" + 3, "long_ld", "" + 1));
+    assertU(adoc("id", "1002", "string_sd", "A", "double_dd", "" + 25, "long_ld", "" + 2));
+    assertU(adoc("id", "1003", "string_sd", "B", "long_ld", "" + 3));
+    assertU(adoc("id", "1004", "string_sd", "B", "long_ld", "" + 4));
+    assertU(adoc("id", "1005", "string_sd", "C",                       "double_dd", "" + 17));
+    
+    assertU(commit());
+    String response = h.query(request(fileToStringArr(ExpressionTest.class, fileName)));
+    setResponse(response);
+  }
+
+  @Test
+  public void addTest() throws Exception {
+    Double minResult = (Double) getStatResult("ar", "min", VAL_TYPE.DOUBLE);
+    Long maxResult = (Long) getStatResult("ar", "max", VAL_TYPE.LONG);
+    assertEquals(Double.valueOf(minResult), Double.valueOf(3.0));
+    assertEquals(Long.valueOf(maxResult),Long.valueOf(4));
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetCloudTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetCloudTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetCloudTest.java
new file mode 100644
index 0000000..b3341b1
--- /dev/null
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetCloudTest.java
@@ -0,0 +1,1214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.common.util.NamedList;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+public class FieldFacetCloudTest extends AbstractAnalyticsFacetCloudTest{
+  public static final int INT = 71;
+  public static final int LONG = 36;
+  public static final int LONGM = 50;
+  public static final int FLOAT = 73;
+  public static final int FLOATM = 84;
+  public static final int DOUBLE = 49;
+  public static final int DATE = 12;
+  public static final int DATEM = 30;
+  public static final int STRING = 29;
+  public static final int STRINGM = 41;
+  public static final int NUM_LOOPS = 100;
+  
+  //INT
+  private static ArrayList<ArrayList<Integer>> intDateTestStart; 
+  private static ArrayList<Long> intDateTestMissing; 
+  private static ArrayList<ArrayList<Integer>> intStringTestStart; 
+  private static ArrayList<Long> intStringTestMissing; 
+  
+  //LONG
+  private static ArrayList<ArrayList<Long>> longDateTestStart; 
+  private static ArrayList<Long> longDateTestMissing; 
+  private static ArrayList<ArrayList<Long>> longStringTestStart; 
+  private static ArrayList<Long> longStringTestMissing; 
+  
+  //FLOAT
+  private static ArrayList<ArrayList<Float>> floatDateTestStart; 
+  private static ArrayList<Long> floatDateTestMissing; 
+  private static ArrayList<ArrayList<Float>> floatStringTestStart; 
+  private static ArrayList<Long> floatStringTestMissing; 
+  
+  //DOUBLE
+  private static ArrayList<ArrayList<Double>> doubleDateTestStart; 
+  private static ArrayList<Long> doubleDateTestMissing; 
+  private static ArrayList<ArrayList<Double>> doubleStringTestStart; 
+  private static ArrayList<Long> doubleStringTestMissing; 
+  
+  //DATE
+  private static ArrayList<ArrayList<String>> dateIntTestStart; 
+  private static ArrayList<Long> dateIntTestMissing; 
+  private static ArrayList<ArrayList<String>> dateLongTestStart; 
+  private static ArrayList<Long> dateLongTestMissing; 
+  
+  //String
+  private static ArrayList<ArrayList<String>> stringIntTestStart; 
+  private static ArrayList<Long> stringIntTestMissing; 
+  private static ArrayList<ArrayList<String>> stringLongTestStart; 
+  private static ArrayList<Long> stringLongTestMissing; 
+  
+  //Multi-Valued
+  private static ArrayList<ArrayList<Integer>> multiLongTestStart; 
+  private static ArrayList<Long> multiLongTestMissing; 
+  private static ArrayList<ArrayList<Integer>> multiStringTestStart; 
+  private static ArrayList<Long> multiStringTestMissing; 
+  private static ArrayList<ArrayList<Integer>> multiDateTestStart; 
+  private static ArrayList<Long> multiDateTestMissing; 
+  
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    setupCluster();
+
+    //INT
+    intDateTestStart = new ArrayList<>();
+    intDateTestMissing = new ArrayList<>();
+    intStringTestStart = new ArrayList<>();
+    intStringTestMissing = new ArrayList<>();
+    
+    //LONG
+    longDateTestStart = new ArrayList<>();
+    longDateTestMissing = new ArrayList<>();
+    longStringTestStart = new ArrayList<>();
+    longStringTestMissing = new ArrayList<>();
+    
+    //FLOAT
+    floatDateTestStart = new ArrayList<>();
+    floatDateTestMissing = new ArrayList<>();
+    floatStringTestStart = new ArrayList<>();
+    floatStringTestMissing = new ArrayList<>();
+    
+    //DOUBLE
+    doubleDateTestStart = new ArrayList<>();
+    doubleDateTestMissing = new ArrayList<>();
+    doubleStringTestStart = new ArrayList<>();
+    doubleStringTestMissing = new ArrayList<>();
+    
+    //DATE
+    dateIntTestStart = new ArrayList<>();
+    dateIntTestMissing = new ArrayList<>();
+    dateLongTestStart = new ArrayList<>();
+    dateLongTestMissing = new ArrayList<>();
+    
+    //String
+    stringIntTestStart = new ArrayList<>();
+    stringIntTestMissing = new ArrayList<>();
+    stringLongTestStart = new ArrayList<>();
+    stringLongTestMissing = new ArrayList<>();
+    
+    //Multi-Valued
+    multiLongTestStart = new ArrayList<>();
+    multiLongTestMissing = new ArrayList<>();
+    multiStringTestStart = new ArrayList<>();
+    multiStringTestMissing = new ArrayList<>();
+    multiDateTestStart = new ArrayList<>();
+    multiDateTestMissing = new ArrayList<>();
+
+    UpdateRequest req = new UpdateRequest();
+    for (int j = 0; j < NUM_LOOPS; ++j) {
+      int i = j%INT;
+      long l = j%LONG;
+      long lm = j%LONGM;
+      float f = j%FLOAT;
+      double d = j%DOUBLE;
+      int dt = j%DATE;
+      int dtm = j%DATEM;
+      int s = j%STRING;
+      int sm = j%STRINGM;
+
+      List<String> fields = new ArrayList<>();
+      fields.add("id"); fields.add("1000"+j);
+      
+      if (dt != 0) {
+      }
+      if( i != 0 ) {
+        fields.add("int_id"); fields.add("" + i);
+      }
+      if( l != 0l ) {
+        fields.add("long_ld"); fields.add("" + l);
+        fields.add("long_ldm"); fields.add("" + l);
+      }
+      if( lm != 0l ) {
+        fields.add("long_ldm"); fields.add("" + lm);
+      }
+      if( f != 0.0f ) {
+        fields.add("float_fd"); fields.add("" + f);
+      }
+      if( d != 0.0d ) {
+        fields.add("double_dd"); fields.add("" + d);
+      }
+      if( dt != 0 ) {
+        fields.add("date_dtd"); fields.add((1800+dt) + "-12-31T23:59:59Z");
+        fields.add("date_dtdm"); fields.add((1800+dt) + "-12-31T23:59:59Z");
+      }
+      if ( dtm != 0 ) {
+        fields.add("date_dtdm"); fields.add((1800+dtm) + "-12-31T23:59:59Z");
+      }
+      if ( s != 0 ) {
+        fields.add("string_sd"); fields.add("str" + s);
+        fields.add("string_sdm"); fields.add("str" + s);
+      }
+      if ( sm != 0 ) {
+        fields.add("string_sdm"); fields.add("str" + sm);
+      }
+      if ( dtm != 0 ) {
+        fields.add("date_dtdm"); fields.add((1800+dtm) + "-12-31T23:59:59Z");
+      }
+      req.add(fields.toArray(new String[0]));
+      
+      if( dt != 0 ){
+        //Dates
+        if (j-DATE<0) {
+          ArrayList<Integer> list1 = new ArrayList<>();
+          if( i != 0 ){
+            list1.add(i);
+            intDateTestMissing.add(0l);
+          } else {
+            intDateTestMissing.add(1l);
+          }
+          intDateTestStart.add(list1);
+          ArrayList<Long> list2 = new ArrayList<>();
+          if( l != 0l ){
+            list2.add(l);
+            longDateTestMissing.add(0l);
+          } else {
+            longDateTestMissing.add(1l);
+          }
+          longDateTestStart.add(list2);
+          ArrayList<Float> list3 = new ArrayList<>();
+          if ( f != 0.0f ){
+            list3.add(f);
+            floatDateTestMissing.add(0l);
+          } else {
+            floatDateTestMissing.add(1l);
+            
+          }
+          floatDateTestStart.add(list3);
+          ArrayList<Double> list4 = new ArrayList<>();
+          if( d != 0.0d ){
+            list4.add(d);
+            doubleDateTestMissing.add(0l);
+          } else {
+            doubleDateTestMissing.add(1l);
+          }
+          doubleDateTestStart.add(list4);
+          ArrayList<Integer> list5 = new ArrayList<>();
+          if( i != 0 ){
+            list5.add(i);
+            multiDateTestMissing.add(0l);
+          } else {
+            multiDateTestMissing.add(1l);
+            
+          }
+          multiDateTestStart.add(list5);
+        } else {
+          if( i != 0 ) intDateTestStart.get(dt-1).add(i); else increment(intDateTestMissing,dt-1);
+          if( l != 0l ) longDateTestStart.get(dt-1).add(l); else increment(longDateTestMissing,dt-1);
+          if( f != 0.0f ) floatDateTestStart.get(dt-1).add(f); else increment(floatDateTestMissing,dt-1);
+          if( d != 0.0d ) doubleDateTestStart.get(dt-1).add(d); else increment(doubleDateTestMissing,dt-1);
+          if( i != 0 ) multiDateTestStart.get(dt-1).add(i); else increment(multiDateTestMissing,dt-1);
+        }
+      }
+      
+      if (j-DATEM<0 && dtm!=dt && dtm!=0) {
+        ArrayList<Integer> list1 = new ArrayList<>();
+        if( i != 0 ){
+          list1.add(i);
+          multiDateTestMissing.add(0l);
+        } else {
+          multiDateTestMissing.add(1l);
+        }
+        multiDateTestStart.add(list1);
+      } else if (dtm!=dt && dtm!=0) {
+        if( i != 0 ) multiDateTestStart.get(dtm-1).add(i);
+      }
+      
+      if( s != 0 ){
+        //Strings
+        if (j-STRING<0) {
+          ArrayList<Integer> list1 = new ArrayList<>();
+          if( i != 0 ){
+            list1.add(i);
+            intStringTestMissing.add(0l);
+          } else {
+            intStringTestMissing.add(1l);
+          }
+          intStringTestStart.add(list1);
+          ArrayList<Long> list2 = new ArrayList<>();
+          if( l != 0l ){
+            list2.add(l);
+            longStringTestMissing.add(0l);
+          } else {
+            longStringTestMissing.add(1l);
+          }
+          longStringTestStart.add(list2);
+          ArrayList<Float> list3 = new ArrayList<>();
+          if( f != 0.0f ){
+            list3.add(f);
+            floatStringTestMissing.add(0l);
+          } else {
+            floatStringTestMissing.add(1l);
+          }
+          floatStringTestStart.add(list3);
+          ArrayList<Double> list4 = new ArrayList<>();
+          if( d != 0.0d ){
+            list4.add(d);
+            doubleStringTestMissing.add(0l);
+          } else {
+            doubleStringTestMissing.add(1l);
+          }
+          doubleStringTestStart.add(list4);
+          ArrayList<Integer> list5 = new ArrayList<>();
+          if( i != 0 ){
+            list5.add(i);
+            multiStringTestMissing.add(0l);
+          } else {
+            multiStringTestMissing.add(1l);
+          }
+          multiStringTestStart.add(list5);
+        } else {
+          if( i != 0 ) intStringTestStart.get(s-1).add(i); else increment(intStringTestMissing,s-1);
+          if( l != 0l ) longStringTestStart.get(s-1).add(l); else increment(longStringTestMissing,s-1);
+          if( f != 0.0f ) floatStringTestStart.get(s-1).add(f); else increment(floatStringTestMissing,s-1);
+          if( d != 0.0d ) doubleStringTestStart.get(s-1).add(d); else increment(doubleStringTestMissing,s-1);
+          if( i != 0 ) multiStringTestStart.get(s-1).add(i); else increment(multiStringTestMissing,s-1);
+        }
+      }
+      
+      //Strings
+      if( sm != 0 ){
+        if (j-STRINGM<0&&sm!=s) {
+          ArrayList<Integer> list1 = new ArrayList<>();
+          if( i != 0 ){
+            list1.add(i);
+            multiStringTestMissing.add(0l);
+          } else {
+            multiStringTestMissing.add(1l);
+          }
+          multiStringTestStart.add(list1);
+        } else if (sm!=s) {
+          if( i != 0 ) multiStringTestStart.get(sm-1).add(i); else increment(multiStringTestMissing,sm-1);
+        }
+      }
+      
+      //Int
+      if( i != 0 ){
+        if (j-INT<0) {
+          ArrayList<String> list1 = new ArrayList<>();
+          if( dt != 0 ){
+            list1.add((1800+dt) + "-12-31T23:59:59Z");
+            dateIntTestMissing.add(0l);
+          } else {
+            dateIntTestMissing.add(1l);
+          }
+          dateIntTestStart.add(list1);
+          ArrayList<String> list2 = new ArrayList<>();
+          if( s != 0 ){
+            list2.add("str"+s);
+            stringIntTestMissing.add(0l);
+          } else {
+            stringIntTestMissing.add(1l);
+          }
+          stringIntTestStart.add(list2);
+        } else {
+          if( dt != 0 ) dateIntTestStart.get(i-1).add((1800+dt) + "-12-31T23:59:59Z"); else increment(dateIntTestMissing,i-1);
+          if( s != 0 ) stringIntTestStart.get(i-1).add("str"+s); else increment(stringIntTestMissing,i-1);
+        }
+      }
+      
+      //Long
+      if( l != 0 ){
+        if (j-LONG<0) {
+          ArrayList<String> list1 = new ArrayList<>();
+          if( dt != 0 ){
+            list1.add((1800+dt) + "-12-31T23:59:59Z");
+            dateLongTestMissing.add(0l);
+          } else {
+            dateLongTestMissing.add(1l);
+          }
+          dateLongTestStart.add(list1);
+          ArrayList<String> list2 = new ArrayList<>();
+          if( s != 0 ){
+            list2.add("str"+s);
+            stringLongTestMissing.add(0l);
+          } else {
+            stringLongTestMissing.add(1l);
+          }
+          stringLongTestStart.add(list2);
+          ArrayList<Integer> list3 = new ArrayList<>();
+          if( i != 0 ){
+            list3.add(i);
+            multiLongTestMissing.add(0l);
+          } else {
+            multiLongTestMissing.add(1l);
+          }
+          multiLongTestStart.add(list3);
+        } else {
+          if( dt != 0 ) dateLongTestStart.get((int)l-1).add((1800+dt) + "-12-31T23:59:59Z"); else increment(dateLongTestMissing,(int)l-1);
+          if( s != 0 ) stringLongTestStart.get((int)l-1).add("str"+s); else increment(stringLongTestMissing,(int)l-1);
+          if( i != 0 ) multiLongTestStart.get((int)l-1).add(i); else increment(multiLongTestMissing,(int)l-1);
+        }
+      }
+      
+      //Long
+      if( lm != 0 ){
+        if (j-LONGM<0&&lm!=l) {
+          ArrayList<Integer> list1 = new ArrayList<>();
+          if( i != 0 ){
+            list1.add(i);
+            multiLongTestMissing.add(0l);
+          } else {
+            multiLongTestMissing.add(1l);
+          }
+          multiLongTestStart.add(list1);
+        } else if (lm!=l) {
+          if( i != 0 ) multiLongTestStart.get((int)lm-1).add(i); else increment( multiLongTestMissing,(int)lm-1);
+        }
+      }
+      
+    }
+
+    req.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
+    
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void sumTest() throws Exception { 
+    String[] params = new String[] {
+        "o.sum.s.int", "sum(int_id)",
+        "o.sum.s.long", "sum(long_ld)",
+        "o.sum.s.float", "sum(float_fd)",
+        "o.sum.s.double", "sum(double_dd)",
+        "o.sum.ff", "string_sd",
+        "o.sum.ff", "date_dtd"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+
+    //Int Date
+    Collection<Double> intDate = getValueList(response, "sum", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Double> intDateTest = calculateNumberStat(intDateTestStart, "sum");
+    assertEquals(responseStr.toString(),intDate,intDateTest);
+    //Int String
+    Collection<Double> intString = getValueList(response, "sum", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Double> intStringTest = calculateNumberStat(intStringTestStart, "sum");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Double> longDate = getValueList(response, "sum", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Double> longDateTest = calculateNumberStat(longDateTestStart, "sum");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Double> longString = getValueList(response, "sum", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Double> longStringTest = calculateNumberStat(longStringTestStart, "sum");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Double> floatDate = getValueList(response, "sum", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Double> floatDateTest = calculateNumberStat(floatDateTestStart, "sum");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Double> floatString = getValueList(response, "sum", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Double> floatStringTest = calculateNumberStat(floatStringTestStart, "sum");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "sum", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = calculateNumberStat(doubleDateTestStart, "sum");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "sum", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = calculateNumberStat(doubleStringTestStart, "sum");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void meanTest() throws Exception { 
+    String[] params = new String[] {
+        "o.mean.s.int", "mean(int_id)",
+        "o.mean.s.long", "mean(long_ld)",
+        "o.mean.s.float", "mean(float_fd)",
+        "o.mean.s.double", "mean(double_dd)",
+        "o.mean.ff", "string_sd",
+        "o.mean.ff", "date_dtd"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Double> intDate = getValueList(response, "mean", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Double> intDateTest = calculateNumberStat(intDateTestStart, "mean");
+    assertEquals(responseStr,intDate,intDateTest);
+    //Int String
+    Collection<Double> intString = getValueList(response, "mean", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Double> intStringTest = calculateNumberStat(intStringTestStart, "mean");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Double> longDate = getValueList(response, "mean", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Double> longDateTest = calculateNumberStat(longDateTestStart, "mean");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Double> longString = getValueList(response, "mean", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Double> longStringTest = calculateNumberStat(longStringTestStart, "mean");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Double> floatDate = getValueList(response, "mean", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Double> floatDateTest = calculateNumberStat(floatDateTestStart, "mean");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Double> floatString = getValueList(response, "mean", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Double> floatStringTest = calculateNumberStat(floatStringTestStart, "mean");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "mean", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = calculateNumberStat(doubleDateTestStart, "mean");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "mean", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = calculateNumberStat(doubleStringTestStart, "mean");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void stddevFacetAscTest() throws Exception { 
+    String[] params = new String[] {
+        "o.stddev.s.int", "stddev(int_id)",
+        "o.stddev.s.long", "stddev(long_ld)",
+        "o.stddev.s.float", "stddev(float_fd)",
+        "o.stddev.s.double", "stddev(double_dd)",
+        "o.stddev.ff", "string_sd",
+        "o.stddev.ff", "date_dtd"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    
+    //Int Date
+    ArrayList<Double> intDate = getValueList(response, "stddev", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Double> intDateTest = calculateNumberStat(intDateTestStart, "stddev");
+    checkStddevs(response, intDate, intDateTest);
+    //Int String
+    ArrayList<Double> intString = getValueList(response, "stddev", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Double> intStringTest = calculateNumberStat(intStringTestStart, "stddev");
+    checkStddevs(response, intString, intStringTest);
+
+    //Long Date
+    ArrayList<Double> longDate = getValueList(response, "stddev", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Double> longDateTest = calculateNumberStat(longDateTestStart, "stddev");
+    checkStddevs(response, longDate, longDateTest);
+    //Long String
+    ArrayList<Double> longString = getValueList(response, "stddev", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Double> longStringTest = calculateNumberStat(longStringTestStart, "stddev");
+    checkStddevs(response, longString, longStringTest);
+
+    //Float Date
+    ArrayList<Double> floatDate = getValueList(response, "stddev", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Double> floatDateTest = calculateNumberStat(floatDateTestStart, "stddev");
+    checkStddevs(response, floatDate, floatDateTest);
+    //Float String
+    ArrayList<Double> floatString = getValueList(response, "stddev", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Double> floatStringTest = calculateNumberStat(floatStringTestStart, "stddev");
+    checkStddevs(response, floatString, floatStringTest);
+
+    //Double Date
+    ArrayList<Double> doubleDate = getValueList(response, "stddev", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = calculateNumberStat(doubleDateTestStart, "stddev");
+    checkStddevs(response, doubleDate, doubleDateTest);
+    //Double String
+    ArrayList<Double> doubleString = getValueList(response, "stddev", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = calculateNumberStat(doubleStringTestStart, "stddev");
+    checkStddevs(response, doubleString, doubleStringTest);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void medianFacetAscTest() throws Exception { 
+    String[] params = new String[] {
+        "o.median.s.int", "median(int_id)",
+        "o.median.s.long", "median(long_ld)",
+        "o.median.s.float", "median(float_fd)",
+        "o.median.s.double", "median(double_dd)",
+        "o.median.ff", "string_sd",
+        "o.median.ff", "date_dtd"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Double> intDate = getValueList(response, "median","fieldFacets", "date_dtd", "int", false);
+    ArrayList<Double> intDateTest = calculateNumberStat(intDateTestStart, "median");
+    assertEquals(responseStr,intDate,intDateTest);
+    //Int String
+    Collection<Double> intString = getValueList(response, "median", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Double> intStringTest = calculateNumberStat(intStringTestStart, "median");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Double> longDate = getValueList(response, "median", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Double> longDateTest = calculateNumberStat(longDateTestStart, "median");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Double> longString = getValueList(response, "median", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Double> longStringTest = calculateNumberStat(longStringTestStart, "median");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Double> floatDate = getValueList(response, "median", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Double> floatDateTest = calculateNumberStat(floatDateTestStart, "median");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Double> floatString = getValueList(response, "median", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Double> floatStringTest = calculateNumberStat(floatStringTestStart, "median");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "median", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = calculateNumberStat(doubleDateTestStart, "median");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "median", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = calculateNumberStat(doubleStringTestStart, "median");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void perc20Test() throws Exception { 
+    String[] params = new String[] {
+        "o.percentile_20n.s.int", "percentile(20,int_id)",
+        "o.percentile_20n.s.long", "percentile(20,long_ld)",
+        "o.percentile_20n.s.float", "percentile(20,float_fd)",
+        "o.percentile_20n.s.double", "percentile(20,double_dd)",
+        "o.percentile_20n.ff", "string_sd",
+        "o.percentile_20n.ff", "date_dtd",
+
+        "o.percentile_20.s.str", "percentile(20,string_sd)",
+        "o.percentile_20.s.date", "string(percentile(20,date_dtd))",
+        "o.percentile_20.ff", "int_id",
+        "o.percentile_20.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Integer> intDate = getValueList(response, "percentile_20n", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Integer> intDateTest = (ArrayList<Integer>)calculateStat(intDateTestStart, "perc_20");
+    assertEquals(responseStr,intDate,intDateTest);
+    //Int String
+    Collection<Integer> intString = getValueList(response, "percentile_20n", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Integer> intStringTest = (ArrayList<Integer>)calculateStat(intStringTestStart, "perc_20");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "percentile_20n", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Long> longDateTest = (ArrayList<Long>)calculateStat(longDateTestStart, "perc_20");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Long> longString = getValueList(response, "percentile_20n", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Long> longStringTest = (ArrayList<Long>)calculateStat(longStringTestStart, "perc_20");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Float> floatDate = getValueList(response, "percentile_20n", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Float> floatDateTest = (ArrayList<Float>)calculateStat(floatDateTestStart, "perc_20");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Float> floatString = getValueList(response, "percentile_20n", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Float> floatStringTest = (ArrayList<Float>)calculateStat(floatStringTestStart, "perc_20");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "percentile_20n", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = (ArrayList<Double>)calculateStat(doubleDateTestStart, "perc_20");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "percentile_20n", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = (ArrayList<Double>)calculateStat(doubleStringTestStart, "perc_20");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+
+    //Date Int
+    Collection<String> dateInt = getValueList(response, "percentile_20", "fieldFacets", "int_id", "date", false);
+    ArrayList<String> dateIntTest = (ArrayList<String>)calculateStat(dateIntTestStart, "perc_20");
+    assertEquals(responseStr,dateInt,dateIntTest);
+    //Date Long
+    Collection<String> dateString = getValueList(response, "percentile_20", "fieldFacets", "long_ld", "date", false);
+    ArrayList<String> dateLongTest = (ArrayList<String>)calculateStat(dateLongTestStart, "perc_20");
+    assertEquals(responseStr,dateString,dateLongTest);
+
+    //String Int
+    Collection<String> stringInt = getValueList(response, "percentile_20", "fieldFacets", "int_id", "str", false);
+    ArrayList<String> stringIntTest = (ArrayList<String>)calculateStat(stringIntTestStart, "perc_20");
+    assertEquals(responseStr,stringInt,stringIntTest);
+    //String Long
+    Collection<String> stringLong = getValueList(response, "percentile_20", "fieldFacets", "long_ld", "str", false);
+    ArrayList<String> stringLongTest = (ArrayList<String>)calculateStat(stringLongTestStart, "perc_20");
+    assertEquals(responseStr,stringLong,stringLongTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void perc60Test() throws Exception { 
+    String[] params = new String[] {
+        "o.percentile_60n.s.int", "percentile(60,int_id)",
+        "o.percentile_60n.s.long", "percentile(60,long_ld)",
+        "o.percentile_60n.s.float", "percentile(60,float_fd)",
+        "o.percentile_60n.s.double", "percentile(60,double_dd)",
+        "o.percentile_60n.ff", "string_sd",
+        "o.percentile_60n.ff", "date_dtd",
+
+        "o.percentile_60.s.str", "percentile(60,string_sd)",
+        "o.percentile_60.s.date", "string(percentile(60,date_dtd))",
+        "o.percentile_60.ff", "int_id",
+        "o.percentile_60.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Integer> intDate = getValueList(response, "percentile_60n", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Integer> intDateTest = (ArrayList<Integer>)calculateStat(intDateTestStart, "perc_60");
+    assertEquals(responseStr,intDate,intDateTest);
+    //Int String
+    Collection<Integer> intString = getValueList(response, "percentile_60n", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Integer> intStringTest = (ArrayList<Integer>)calculateStat(intStringTestStart, "perc_60");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "percentile_60n", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Long> longDateTest = (ArrayList<Long>)calculateStat(longDateTestStart, "perc_60");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Long> longString = getValueList(response, "percentile_60n", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Long> longStringTest = (ArrayList<Long>)calculateStat(longStringTestStart, "perc_60");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Float> floatDate = getValueList(response, "percentile_60n", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Float> floatDateTest = (ArrayList<Float>)calculateStat(floatDateTestStart, "perc_60");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Float> floatString = getValueList(response, "percentile_60n", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Float> floatStringTest = (ArrayList<Float>)calculateStat(floatStringTestStart, "perc_60");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "percentile_60n", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = (ArrayList<Double>)calculateStat(doubleDateTestStart, "perc_60");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "percentile_60n", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = (ArrayList<Double>)calculateStat(doubleStringTestStart, "perc_60");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+
+    //Date Int
+    Collection<String> dateInt = getValueList(response, "percentile_60", "fieldFacets", "int_id", "date", false);
+    ArrayList<String> dateIntTest = (ArrayList<String>)calculateStat(dateIntTestStart, "perc_60");
+    assertEquals(responseStr,dateInt,dateIntTest);
+    //Date Long
+    Collection<String> dateString = getValueList(response, "percentile_60", "fieldFacets", "long_ld", "date", false);
+    ArrayList<String> dateLongTest = (ArrayList<String>)calculateStat(dateLongTestStart, "perc_60");
+    assertEquals(responseStr,dateString,dateLongTest);
+
+    //String Int
+    Collection<String> stringInt = getValueList(response, "percentile_60", "fieldFacets", "int_id", "str", false);
+    ArrayList<String> stringIntTest = (ArrayList<String>)calculateStat(stringIntTestStart, "perc_60");
+    assertEquals(responseStr,stringInt,stringIntTest);
+    //String Long
+    Collection<String> stringLong = getValueList(response, "percentile_60", "fieldFacets", "long_ld", "str", false);
+    ArrayList<String> stringLongTest = (ArrayList<String>)calculateStat(stringLongTestStart, "perc_60");
+    assertEquals(responseStr,stringLong,stringLongTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void minTest() throws Exception { 
+    String[] params = new String[] {
+        "o.minn.s.int", "min(int_id)",
+        "o.minn.s.long", "min(long_ld)",
+        "o.minn.s.float", "min(float_fd)",
+        "o.minn.s.double", "min(double_dd)",
+        "o.minn.ff", "string_sd",
+        "o.minn.ff", "date_dtd",
+
+        "o.min.s.str", "min(string_sd)",
+        "o.min.s.date", "string(min(date_dtd))",
+        "o.min.ff", "int_id",
+        "o.min.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Integer> intDate = getValueList(response, "minn", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Integer> intDateTest = (ArrayList<Integer>)calculateStat(intDateTestStart, "min");
+    assertEquals(responseStr,intDate,intDateTest);
+    //Int String
+    Collection<Integer> intString = getValueList(response, "minn", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Integer> intStringTest = (ArrayList<Integer>)calculateStat(intStringTestStart, "min");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "minn", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Long> longDateTest = (ArrayList<Long>)calculateStat(longDateTestStart, "min");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Long> longString = getValueList(response, "minn", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Long> longStringTest = (ArrayList<Long>)calculateStat(longStringTestStart, "min");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Float> floatDate = getValueList(response, "minn", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Float> floatDateTest = (ArrayList<Float>)calculateStat(floatDateTestStart, "min");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Float> floatString = getValueList(response, "minn", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Float> floatStringTest = (ArrayList<Float>)calculateStat(floatStringTestStart, "min");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "minn", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = (ArrayList<Double>)calculateStat(doubleDateTestStart, "min");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "minn", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = (ArrayList<Double>)calculateStat(doubleStringTestStart, "min");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+
+    //Date Int
+    Collection<String> dateInt = getValueList(response, "min", "fieldFacets", "int_id", "date", false);
+    ArrayList<String> dateIntTest = (ArrayList<String>)calculateStat(dateIntTestStart, "min");
+    assertEquals(responseStr,dateInt,dateIntTest);
+    //Date Long
+    Collection<String> dateString = getValueList(response, "min", "fieldFacets", "long_ld", "date", false);
+    ArrayList<String> dateLongTest = (ArrayList<String>)calculateStat(dateLongTestStart, "min");
+    assertEquals(responseStr,dateString,dateLongTest);
+
+    //String Int
+    Collection<String> stringInt = getValueList(response, "min", "fieldFacets", "int_id", "str", false);
+    ArrayList<String> stringIntTest = (ArrayList<String>)calculateStat(stringIntTestStart, "min");
+    assertEquals(responseStr,stringInt,stringIntTest);
+    //String Long
+    Collection<String> stringLong = getValueList(response, "min", "fieldFacets", "long_ld", "str", false);
+    ArrayList<String> stringLongTest = (ArrayList<String>)calculateStat(stringLongTestStart, "min");
+    assertEquals(responseStr,stringLong,stringLongTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void maxTest() throws Exception { 
+    String[] params = new String[] {
+        "o.maxn.s.int", "max(int_id)",
+        "o.maxn.s.long", "max(long_ld)",
+        "o.maxn.s.float", "max(float_fd)",
+        "o.maxn.s.double", "max(double_dd)",
+        "o.maxn.ff", "string_sd",
+        "o.maxn.ff", "date_dtd",
+
+        "o.max.s.str", "max(string_sd)",
+        "o.max.s.date", "string(max(date_dtd))",
+        "o.max.ff", "int_id",
+        "o.max.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Integer> intDate = getValueList(response, "maxn", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Integer> intDateTest = (ArrayList<Integer>)calculateStat(intDateTestStart, "max");
+    //assertEquals(responseStr,intDate,intDateTest);
+    
+    //Int String
+    Collection<Integer> intString = getValueList(response, "maxn", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Integer> intStringTest = (ArrayList<Integer>)calculateStat(intStringTestStart, "max");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "maxn", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Long> longDateTest = (ArrayList<Long>)calculateStat(longDateTestStart, "max");
+    assertEquals(responseStr,longDate,longDateTest);
+    
+    //Long String
+    Collection<Long> longString = getValueList(response, "maxn", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Long> longStringTest = (ArrayList<Long>)calculateStat(longStringTestStart, "max");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Float> floatDate = getValueList(response, "maxn", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Float> floatDateTest = (ArrayList<Float>)calculateStat(floatDateTestStart, "max");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    
+    //Float String
+    Collection<Float> floatString = getValueList(response, "maxn", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Float> floatStringTest = (ArrayList<Float>)calculateStat(floatStringTestStart, "max");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "maxn", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = (ArrayList<Double>)calculateStat(doubleDateTestStart, "max");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "maxn", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = (ArrayList<Double>)calculateStat(doubleStringTestStart, "max");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+    
+    //String Int
+    Collection<String> stringInt = getValueList(response, "max", "fieldFacets", "int_id", "str", false);
+    ArrayList<String> stringIntTest = (ArrayList<String>)calculateStat(stringIntTestStart, "max");
+    assertEquals(responseStr,stringInt,stringIntTest);
+    
+    //String Long
+    Collection<String> stringLong = getValueList(response, "max", "fieldFacets", "long_ld", "str", false);
+    ArrayList<String> stringLongTest = (ArrayList<String>)calculateStat(stringLongTestStart, "max");
+    assertEquals(responseStr,stringLong,stringLongTest);
+
+    //Date Int
+    Collection<String> dateInt = getValueList(response, "max", "fieldFacets", "int_id", "date", false);
+    ArrayList<String> dateIntTest = (ArrayList<String>)calculateStat(dateIntTestStart, "max");
+    assertEquals(responseStr,dateInt,dateIntTest);
+    
+    //Date Long
+    Collection<String> dateString = getValueList(response, "max", "fieldFacets", "long_ld", "date", false);
+    ArrayList<String> dateLongTest = (ArrayList<String>)calculateStat(dateLongTestStart, "max");
+    assertEquals(responseStr,dateString,dateLongTest);
+
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void uniqueTest() throws Exception { 
+    String[] params = new String[] {
+        "o.uniquen.s.int", "unique(int_id)",
+        "o.uniquen.s.long", "unique(long_ld)",
+        "o.uniquen.s.float", "unique(float_fd)",
+        "o.uniquen.s.double", "unique(double_dd)",
+        "o.uniquen.ff", "string_sd",
+        "o.uniquen.ff", "date_dtd",
+
+        "o.unique.s.str", "unique(string_sd)",
+        "o.unique.s.date", "unique(date_dtd)",
+        "o.unique.ff", "int_id",
+        "o.unique.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Long> intDate = getValueList(response, "uniquen", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Long> intDateTest = (ArrayList<Long>)calculateStat(intDateTestStart, "unique");
+    assertEquals(responseStr,intDate,intDateTest);
+    //Int String
+    Collection<Long> intString = getValueList(response, "uniquen", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Long> intStringTest = (ArrayList<Long>)calculateStat(intStringTestStart, "unique");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "uniquen", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Long> longDateTest = (ArrayList<Long>)calculateStat(longDateTestStart, "unique");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Long> longString = getValueList(response, "uniquen", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Long> longStringTest = (ArrayList<Long>)calculateStat(longStringTestStart, "unique");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Long> floatDate = getValueList(response, "uniquen", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Long> floatDateTest = (ArrayList<Long>)calculateStat(floatDateTestStart, "unique");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Long> floatString = getValueList(response, "uniquen", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Long> floatStringTest = (ArrayList<Long>)calculateStat(floatStringTestStart, "unique");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Long> doubleDate = getValueList(response, "uniquen", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Long> doubleDateTest = (ArrayList<Long>)calculateStat(doubleDateTestStart, "unique");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Long> doubleString = getValueList(response, "uniquen", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Long> doubleStringTest = (ArrayList<Long>)calculateStat(doubleStringTestStart, "unique");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+
+    //Date Int
+    Collection<Long> dateInt = getValueList(response, "unique", "fieldFacets", "int_id", "date", false);
+    ArrayList<Long> dateIntTest = (ArrayList<Long>)calculateStat(dateIntTestStart, "unique");
+    assertEquals(responseStr,dateInt,dateIntTest);
+    //Date Long
+    Collection<Long> dateString = getValueList(response, "unique", "fieldFacets", "long_ld", "date", false);
+    ArrayList<Long> dateLongTest = (ArrayList<Long>)calculateStat(dateLongTestStart, "unique");
+    assertEquals(responseStr,dateString,dateLongTest);
+
+    //String Int
+    Collection<Long> stringInt = getValueList(response, "unique", "fieldFacets", "int_id", "str", false);
+    ArrayList<Long> stringIntTest = (ArrayList<Long>)calculateStat(stringIntTestStart, "unique");
+    assertEquals(responseStr,stringInt,stringIntTest);
+    //String Long
+    Collection<Long> stringLong = getValueList(response, "unique", "fieldFacets", "long_ld", "str", false);
+    ArrayList<Long> stringLongTest = (ArrayList<Long>)calculateStat(stringLongTestStart, "unique");
+    assertEquals(responseStr,stringLong,stringLongTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void countTest() throws Exception { 
+    String[] params = new String[] {
+        "o.countn.s.int", "count(int_id)",
+        "o.countn.s.long", "count(long_ld)",
+        "o.countn.s.float", "count(float_fd)",
+        "o.countn.s.double", "count(double_dd)",
+        "o.countn.ff", "string_sd",
+        "o.countn.ff", "date_dtd",
+
+        "o.count.s.str", "count(string_sd)",
+        "o.count.s.date", "count(date_dtd)",
+        "o.count.ff", "int_id",
+        "o.count.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Long> intDate = getValueList(response, "countn", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Long> intDateTest = (ArrayList<Long>)calculateStat(intDateTestStart, "count");
+    assertEquals(responseStr,intDate,intDateTest);
+    
+    //Int String
+    Collection<Long> intString = getValueList(response, "countn", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Long> intStringTest = (ArrayList<Long>)calculateStat(intStringTestStart, "count");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "countn", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Long> longDateTest = (ArrayList<Long>)calculateStat(longDateTestStart, "count");
+    assertEquals(responseStr,longDate,longDateTest);
+    
+    //Long String
+    Collection<Long> longString = getValueList(response, "countn", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Long> longStringTest = (ArrayList<Long>)calculateStat(longStringTestStart, "count");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Long> floatDate = getValueList(response, "countn", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Long> floatDateTest = (ArrayList<Long>)calculateStat(floatDateTestStart, "count");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    
+    //Float String
+    Collection<Long> floatString = getValueList(response, "countn", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Long> floatStringTest = (ArrayList<Long>)calculateStat(floatStringTestStart, "count");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Long> doubleDate = getValueList(response, "countn", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Long> doubleDateTest = (ArrayList<Long>)calculateStat(doubleDateTestStart, "count");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    
+    //Double String
+    Collection<Long> doubleString = getValueList(response, "countn", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Long> doubleStringTest = (ArrayList<Long>)calculateStat(doubleStringTestStart, "count");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+
+    //Date Int
+    Collection<Long> dateInt = getValueList(response, "count", "fieldFacets", "int_id", "date", false);
+    ArrayList<Long> dateIntTest = (ArrayList<Long>)calculateStat(dateIntTestStart, "count");
+    assertEquals(responseStr,dateIntTest,dateInt);
+    
+    //Date Long
+    Collection<Long> dateLong = getValueList(response, "count", "fieldFacets", "long_ld", "date", false);
+    ArrayList<Long> dateLongTest = (ArrayList<Long>)calculateStat(dateLongTestStart, "count");
+    assertEquals(responseStr,dateLong,dateLongTest);
+
+    //String Int
+    Collection<Long> stringInt = getValueList(response, "count", "fieldFacets", "int_id", "str", false);
+    ArrayList<Long> stringIntTest = (ArrayList<Long>)calculateStat(stringIntTestStart, "count");
+    assertEquals(responseStr,stringInt,stringIntTest);
+    
+    //String Long
+    Collection<Long> stringLong = getValueList(response, "count", "fieldFacets", "long_ld", "str", false);
+    ArrayList<Long> stringLongTest = (ArrayList<Long>)calculateStat(stringLongTestStart, "count");
+    assertEquals(responseStr,stringLong,stringLongTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void missingTest() throws Exception { 
+    String[] params = new String[] {
+        "o.missingn.s.int", "missing(int_id)",
+        "o.missingn.s.long", "missing(long_ld)",
+        "o.missingn.s.float", "missing(float_fd)",
+        "o.missingn.s.double", "missing(double_dd)",
+        "o.missingn.ff", "string_sd",
+        "o.missingn.ff", "date_dtd",
+
+        "o.missing.s.str", "missing(string_sd)",
+        "o.missing.s.date", "missing(date_dtd)",
+        "o.missing.ff", "int_id",
+        "o.missing.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Long> intDate = getValueList(response, "missingn", "fieldFacets", "date_dtd", "int", false);
+    setLatestType("int");
+    assertEquals(responseStr,intDateTestMissing,intDate);
+    
+    //Int String
+    Collection<Long> intString = getValueList(response, "missingn", "fieldFacets", "string_sd", "int", false);
+    assertEquals(responseStr,intStringTestMissing,intString);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "missingn", "fieldFacets", "date_dtd", "long", false);
+    setLatestType("long");
+    assertEquals(responseStr,longDateTestMissing,longDate);
+    
+    //Long String
+    Collection<Long> longString = getValueList(response, "missingn", "fieldFacets", "string_sd", "long", false);
+    assertEquals(responseStr,longStringTestMissing,longString);
+
+    //Float Date
+    Collection<Long> floatDate = getValueList(response, "missingn", "fieldFacets", "date_dtd", "float", false);
+    setLatestType("float");
+    assertEquals(responseStr,floatDateTestMissing,floatDate);
+    
+    //Float String
+    Collection<Long> floatString = getValueList(response, "missingn", "fieldFacets", "string_sd", "float", false);
+    assertEquals(responseStr,floatStringTestMissing,floatString);
+
+    //Double Date
+    Collection<Long> doubleDate = getValueList(response, "missingn", "fieldFacets", "date_dtd", "double", false);
+    setLatestType("double");
+    assertEquals(responseStr,doubleDateTestMissing,doubleDate);
+    
+    //Double String
+    Collection<Long> doubleString = getValueList(response, "missingn", "fieldFacets", "string_sd", "double", false);
+    assertEquals(responseStr,doubleStringTestMissing,doubleString);
+
+    //Date Int
+    Collection<Long> dateInt = getValueList(response, "missing", "fieldFacets", "int_id", "date", false);
+    setLatestType("date");
+    assertEquals(responseStr,dateIntTestMissing,dateInt);
+    
+    //Date Long
+    Collection<Long> dateLong = getValueList(response, "missing", "fieldFacets", "long_ld", "date", false);
+    assertEquals(responseStr,dateLongTestMissing,dateLong);
+
+    //String Int
+    Collection<Long> stringInt = getValueList(response, "missing", "fieldFacets", "int_id", "str", false);
+    setLatestType("string");
+    assertEquals(responseStr,stringIntTestMissing,stringInt);
+    
+    //String Long
+    Collection<Long> stringLong = getValueList(response, "missing", "fieldFacets", "long_ld", "str", false);
+    assertEquals(responseStr,stringLongTestMissing,stringLong);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void multiValueTest() throws Exception { 
+    String[] params = new String[] {
+        "o.multivalued.s.mean", "mean(int_id)",
+        "o.multivalued.ff", "long_ldm",
+        "o.multivalued.ff", "string_sdm",
+        "o.multivalued.ff", "date_dtdm"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Long
+    Collection<Double> lon = getValueList(response, "multivalued", "fieldFacets", "long_ldm", "mean", false);
+    ArrayList<Double> longTest = calculateNumberStat(multiLongTestStart, "mean");
+    assertEquals(responseStr,lon,longTest);
+    //Date
+    Collection<Double> date = getValueList(response, "multivalued", "fieldFacets", "date_dtdm", "mean", false);
+    ArrayList<Double> dateTest = calculateNumberStat(multiDateTestStart, "mean");
+    assertEquals(responseStr,date,dateTest);
+    //String
+    Collection<Double> string = getValueList(response, "multivalued", "fieldFacets", "string_sdm", "mean", false);
+    ArrayList<Double> stringTest = calculateNumberStat(multiStringTestStart, "mean");
+    assertEquals(responseStr,string,stringTest);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void missingFacetTest() throws Exception { 
+    String[] params = new String[] {
+        "o.func.facet_show_missing(a)", "fillmissing(a,\"(MISSING)\")",
+        "o.missingf.s.mean", "mean(int_id)",
+        "o.missingf.ff", "date_dtd",
+        "o.missingf.ff", "string_sd",
+        "o.missingf.ff.string_sd.sm", "true",
+        "o.missingf.ff", "date_dtdm",
+        "o.missingf.ff.date_dtdm.sm", "true"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //int MultiDate
+    assertTrue(responseStr, responseContainsFacetValue(response, "missingf", "fieldFacets", "date_dtdm", "(MISSING)"));
+    ArrayList<Double> string = getValueList(response, "missingf", "fieldFacets", "date_dtdm", "mean", false);
+    ArrayList<Double> stringTest = calculateNumberStat(multiDateTestStart, "mean");
+    assertEquals(responseStr, string,stringTest);
+    
+    //Int String
+    assertTrue(responseStr, responseContainsFacetValue(response, "missingf", "fieldFacets", "string_sd", "(MISSING)"));
+    assertTrue(responseStr, !responseContainsFacetValue(response, "missingf", "fieldFacets", "string_sd", "str0"));
+    List<Double> intString = getValueList(response, "missingf", "fieldFacets", "string_sd", "mean", false);
+    ArrayList<Double> intStringTest = calculateNumberStat(intStringTestStart, "mean");
+    assertEquals(responseStr, intString,intStringTest);
+    
+    //Int Date
+    Collection<Double> intDate = getValueList(response, "missingf", "fieldFacets", "date_dtd", "mean", false);
+    ArrayList<ArrayList<Double>> intDateMissingTestStart = (ArrayList<ArrayList<Double>>) intDateTestStart.clone();
+    ArrayList<Double> intDateTest = calculateNumberStat(intDateMissingTestStart, "mean");
+    assertEquals(responseStr,intDate,intDateTest);
+  }
+
+  private void checkStddevs(NamedList<Object> response, ArrayList<Double> list1, ArrayList<Double> list2) {
+    Collections.sort(list1);
+    Collections.sort(list2);
+    for (int i = 0; i<list2.size(); i++) {
+      if ((Math.abs(list1.get(i)-list2.get(i))<.00000000001) == false) {
+        Assert.assertEquals(response.toString(), list1.get(i), list2.get(i), 0.00000000001);
+      }
+    }
+  }
+
+  public static void assertEquals(String mes, Object actual, Object expected) {
+    Collections.sort((List<Comparable>) actual);
+    Collections.sort((List<Comparable>)  expected);
+    Assert.assertEquals(mes, actual, expected);
+  }
+}