You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by ht...@apache.org on 2019/07/19 23:29:09 UTC

[asterixdb] branch master updated: [ASTERIXDB-2614][TEST] Make type computer test argument count aware

This is an automated email from the ASF dual-hosted git repository.

htowaileb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 655e189  [ASTERIXDB-2614][TEST] Make type computer test argument count aware
655e189 is described below

commit 655e189f2c81afe41e3b16da3e26a24627a8bef5
Author: Hussain Towaileb <Hu...@Couchbase.com>
AuthorDate: Thu Jul 18 03:41:58 2019 +0300

    [ASTERIXDB-2614][TEST] Make type computer test argument count aware
    
    - user model changes: no
    - storage format changes: no
    - interface changes: no
    
    Details:
    - Obtained the number of arguments from each function's arity to
      know how many arguments to pass for each type computer instead
      of constantly passing only 2 arguments.
    - Limited the number of arguments to be passed in case of VARARGS
      or functions with arguments more than 3, this could lead to the
      test taking too long and timing out and failing.
    
    Change-Id: I7188d92101990a6b232c0915f127fbfbf3f6f841
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/3500
    Sonar-Qube: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Reviewed-by: Hussain Towaileb <hu...@gmail.com>
    Reviewed-by: Ali Alsuliman <al...@gmail.com>
---
 .../test/om/typecomputer/ExceptionTest.java        | 105 ++++++++++++++++++---
 1 file changed, 93 insertions(+), 12 deletions(-)

diff --git a/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/ExceptionTest.java b/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/ExceptionTest.java
index 95e669f..91752f7 100644
--- a/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/ExceptionTest.java
+++ b/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/ExceptionTest.java
@@ -26,9 +26,12 @@ import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
+import org.apache.asterix.om.functions.BuiltinFunctions;
 import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
 import org.apache.asterix.om.types.ATypeTag;
 import org.apache.asterix.om.types.BuiltinType;
@@ -40,6 +43,7 @@ import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
 import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.LogManager;
@@ -59,18 +63,25 @@ import org.reflections.scanners.SubTypesScanner;
  *
  * Care needs to be taken when deciding the number of arguments, below is how the tests are calculated:
  * The number of combinations is = n ^ m
- * n = number of arguments
- * m = number of types available
+ * n = number of types available
+ * m = number of arguments to pass
  *
  * Example:
- * 2 arguments, 40 types = 1600 combinations per type computer
- * 3 arguments, 40 types = 64000 combinations per type computer
+ * 2 arguments, 40 types = 40 ^ 2 = 1,600 combinations per type computer
+ * 3 arguments, 40 types = 40 ^ 3 = 64,000 combinations per type computer
+ * 4 arguments, 40 types = 40 ^ 4 = 2,560,000 combinations per type computer
  *
- * TODO There are 2 functions that expect a minimum arguments of 3, so passing them 2 arguments will cause them
- * to return an exception, so they're really not being tested properly now. Probably need to add an exception list
- * for such functions.
- * Ideally, making the arguments in the test to be 3 will solve the issue, but that would push the tests to 64000 each
- * and that takes too long and times out the test apparently.
+ * Choice of number of arguments:
+ * 1- To know the proper number of arguments for each type computer, we are going over all the available functions,
+ *    getting their arity and their type computer and comparing them as follows:
+ *     - If a function has VARARGS, that type computer is marked as VARARGS.
+ *     - If multiple functions use the same type computer, the highest arity of all functions is used for that computer.
+ * 2- In case of VARARGS or type computers that handle more than 3 arguments, we will use only 3 arguments, for the
+ *    following reasons:
+ *     - Going over 3 arguments will result in over 2,500,000 test cases, which will time out and fail the test.
+ *     - (As of now) all the type computers using VARARGS need a minimum of 3 arguments or less to function properly,
+ *       so passing 3 arguments will suffice to include all cases.
+ *     - (As of now) all the type computers that handle more than 3 arguments return a constant type, nothing to test.
  */
 
 @RunWith(Parameterized.class)
@@ -78,9 +89,11 @@ public class ExceptionTest {
 
     private static final Logger LOGGER = LogManager.getLogger();
 
-    // Number of arguments to be passed. Number of combinations depends on number of arguments
-    private static int numberOfArguments = 2;
-    private static int numberOfCombinations = (int) Math.pow(ATypeTag.values().length, numberOfArguments);
+    // Caution: Using more than 3 arguments will generate millions of combinations and the test will timeout and fail
+    private static final int MAXIMUM_ARGUMENTS_ALLOWED = 3;
+
+    // This map will hold each used type computer and its highest arity, which represents arguments number to pass
+    private static Map<String, Integer> typeComputerToArgsCountMap = new HashMap<>();
 
     // Test parameters
     @Parameter
@@ -95,6 +108,55 @@ public class ExceptionTest {
         // Prepare tests
         List<Object[]> tests = new ArrayList<>();
 
+        // First, we will go over all the functions available, get their arity and type computers to know the number
+        // of arguments to pass for each type computer
+        Map<IFunctionInfo, IResultTypeComputer> funTypeComputerMap;
+        try {
+            Field field = BuiltinFunctions.class.getDeclaredField("funTypeComputer");
+            field.setAccessible(true);
+            funTypeComputerMap = (HashMap<IFunctionInfo, IResultTypeComputer>) field.get(null);
+        } catch (Exception ex) {
+            // this should never fail
+            throw new IllegalStateException();
+        }
+
+        if (funTypeComputerMap != null) {
+            // Note: If a type computer handles both known and VARARGS, VARARGS will be used
+            for (HashMap.Entry<IFunctionInfo, IResultTypeComputer> entry : funTypeComputerMap.entrySet()) {
+                // Some functions have a null type computer for some reason, ignore them
+                if (entry.getValue() == null) {
+                    continue;
+                }
+
+                // Type computer does not exist, add it with its arity to the map
+                if (typeComputerToArgsCountMap.get(entry.getValue().getClass().getSimpleName()) == null) {
+                    typeComputerToArgsCountMap.put(entry.getValue().getClass().getSimpleName(),
+                            entry.getKey().getFunctionIdentifier().getArity());
+                    continue;
+                }
+
+                // VARARGS functions, these are kept as is, put/update, no need for any comparison
+                if (entry.getKey().getFunctionIdentifier().getArity() == FunctionIdentifier.VARARGS) {
+                    typeComputerToArgsCountMap.put(entry.getValue().getClass().getSimpleName(),
+                            entry.getKey().getFunctionIdentifier().getArity());
+                    continue;
+                }
+
+                // We have it already, and it is of type VARARGS, we are not going to change it
+                if (typeComputerToArgsCountMap
+                        .get(entry.getValue().getClass().getSimpleName()) == FunctionIdentifier.VARARGS) {
+                    continue;
+                }
+
+                // We have it already, if it has larger arity than our existing one, we will update it
+                if (typeComputerToArgsCountMap.get(entry.getValue().getClass().getSimpleName()) < entry.getKey()
+                        .getFunctionIdentifier().getArity()) {
+                    typeComputerToArgsCountMap.put(entry.getValue().getClass().getSimpleName(),
+                            entry.getKey().getFunctionIdentifier().getArity());
+                }
+            }
+        }
+
         // Tests all usual type computers.
         Reflections reflections = new Reflections("org.apache.asterix.om.typecomputer", new SubTypesScanner(false));
         Set<Class<? extends IResultTypeComputer>> classes = reflections.getSubTypesOf(IResultTypeComputer.class);
@@ -113,8 +175,27 @@ public class ExceptionTest {
 
     @Test
     public void test() throws Exception {
+        // If a type computer is not found in the map, then it is not used by any function
+        if (typeComputerToArgsCountMap.get(clazz.getSimpleName()) == null) {
+            LOGGER.log(Level.INFO, "TypeComputer " + clazz.getSimpleName() + " is not used by any functions");
+            return;
+        }
 
+        // Refer to documentation on the top for the details of choosing the arguments count
         // Arguments list
+        int typeComputerMaxArgs = typeComputerToArgsCountMap.get(clazz.getSimpleName());
+
+        // If type computer takes zero arguments, there is nothing to do
+        if (typeComputerMaxArgs == 0) {
+            return;
+        }
+
+        // Calculate number of arguments and number of combinations
+        int numberOfArguments =
+                (typeComputerMaxArgs > MAXIMUM_ARGUMENTS_ALLOWED || typeComputerMaxArgs == FunctionIdentifier.VARARGS)
+                        ? MAXIMUM_ARGUMENTS_ALLOWED : typeComputerMaxArgs;
+        int numberOfCombinations = (int) Math.pow(ATypeTag.values().length, numberOfArguments);
+
         Object[] opaqueParameters = new Object[numberOfArguments];
         List<Mutable<ILogicalExpression>> argumentsList = new ArrayList<>(numberOfArguments);
         for (int i = 0; i < numberOfArguments; i++) {