Repository: asterixdb Updated Branches: refs/heads/master bc3f9b2f0 -> 2816885d1
ASTERIXDB-1631: let TypeComputeUtils handle input type ANY properly. Change-Id: Ie6b3f0e9d9b4ddd9280e06f72a5ca30aa776315d Reviewed-on: https://asterix-gerrit.ics.uci.edu/1191 Sonar-Qube: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Reviewed-by: Till Westmann <ti...@apache.org> Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/2816885d Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/2816885d Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/2816885d Branch: refs/heads/master Commit: 2816885d1a4a2efd969df78abc0b735e40f65a38 Parents: bc3f9b2 Author: Yingyi Bu <yin...@couchbase.com> Authored: Tue Sep 20 18:48:15 2016 -0700 Committer: Yingyi Bu <buyin...@gmail.com> Committed: Tue Sep 20 22:48:29 2016 -0700 ---------------------------------------------------------------------- asterixdb/asterix-om/pom.xml | 6 + .../om/functions/AsterixBuiltinFunctions.java | 4 +- .../impl/FlowRecordResultTypeComputer.java | 45 ------- .../impl/NotMissingTypeComputer.java | 77 ------------ .../impl/NotUnknownTypeComputer.java | 53 +++++++++ .../impl/NullableDoubleTypeComputer.java | 2 +- .../impl/RecordAddFieldsTypeComputer.java | 4 +- .../impl/SubsetCollectionTypeComputer.java | 3 + .../om/typecomputer/impl/TypeComputeUtils.java | 35 ++++-- .../om/typecomputer/TypeComputerTest.java | 116 +++++++++++++++++++ 10 files changed, 206 insertions(+), 139 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/pom.xml ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-om/pom.xml b/asterixdb/asterix-om/pom.xml index 60fa26c..72bf65e 100644 --- a/asterixdb/asterix-om/pom.xml +++ b/asterixdb/asterix-om/pom.xml @@ -74,5 +74,11 @@ <artifactId>junit</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <version>1.10.19</version> + <scope>test</scope> + </dependency> </dependencies> </project> http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java index 184dd84..a85d33b 100644 --- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java +++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java @@ -68,7 +68,7 @@ import org.apache.asterix.om.typecomputer.impl.InjectFailureTypeComputer; import org.apache.asterix.om.typecomputer.impl.LocalAvgTypeComputer; import org.apache.asterix.om.typecomputer.impl.MinMaxAggTypeComputer; import org.apache.asterix.om.typecomputer.impl.NonTaggedGetItemResultType; -import org.apache.asterix.om.typecomputer.impl.NotMissingTypeComputer; +import org.apache.asterix.om.typecomputer.impl.NotUnknownTypeComputer; import org.apache.asterix.om.typecomputer.impl.NullableDoubleTypeComputer; import org.apache.asterix.om.typecomputer.impl.NumericAddSubMulDivTypeComputer; import org.apache.asterix.om.typecomputer.impl.NumericAggTypeComputer; @@ -810,7 +810,7 @@ public class AsterixBuiltinFunctions { addFunction(DEEP_EQUAL, BooleanFunctionTypeComputer.INSTANCE, true); // and then, Asterix builtin functions - addPrivateFunction(CHECK_UNKNOWN, NotMissingTypeComputer.INSTANCE, true); + addPrivateFunction(CHECK_UNKNOWN, NotUnknownTypeComputer.INSTANCE, true); addPrivateFunction(ANY_COLLECTION_MEMBER, CollectionMemberResultType.INSTANCE, true); addFunction(BOOLEAN_CONSTRUCTOR, StringBooleanTypeComputer.INSTANCE, true); addFunction(CARET, NumericAddSubMulDivTypeComputer.INSTANCE, true); http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/FlowRecordResultTypeComputer.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/FlowRecordResultTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/FlowRecordResultTypeComputer.java deleted file mode 100644 index 27e8a3d..0000000 --- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/FlowRecordResultTypeComputer.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.asterix.om.typecomputer.impl; - -import org.apache.asterix.om.typecomputer.base.IResultTypeComputer; -import org.apache.asterix.om.typecomputer.base.TypeCastUtils; -import org.apache.asterix.om.types.IAType; -import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException; -import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression; -import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment; -import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression; -import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider; - -public class FlowRecordResultTypeComputer implements IResultTypeComputer { - - public static final FlowRecordResultTypeComputer INSTANCE = new FlowRecordResultTypeComputer(); - - @Override - public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env, - IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException { - ScalarFunctionCallExpression funcExpr = (ScalarFunctionCallExpression) expression; - IAType type = TypeCastUtils.getRequiredType(funcExpr); - if (type == null) { - type = (IAType) env.getType(funcExpr.getArguments().get(0).getValue()); - } - return type; - } -} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotMissingTypeComputer.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotMissingTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotMissingTypeComputer.java deleted file mode 100644 index 68444c4..0000000 --- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotMissingTypeComputer.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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.asterix.om.typecomputer.impl; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.asterix.om.typecomputer.base.IResultTypeComputer; -import org.apache.asterix.om.types.ATypeTag; -import org.apache.asterix.om.types.AUnionType; -import org.apache.asterix.om.types.IAType; -import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException; -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.metadata.IMetadataProvider; - -/** - * This class is the type computer for not-missing function. - * If the input type is not a union, we just return it. - * If the input type is a union, - * case 1: we return a new union without missing if the new union still has more than one types; - * case 2: we return the non-missing item type in the original union if there are only missing - * and it in the original union. - */ -public class NotMissingTypeComputer implements IResultTypeComputer { - - public static final NotMissingTypeComputer INSTANCE = new NotMissingTypeComputer(); - - @Override - public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env, - IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException { - AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) expression; - IAType type = (IAType) env.getType(f.getArguments().get(0).getValue()); - if (type.getTypeTag() != ATypeTag.UNION) { - // directly return the input type if it is not a union - return type; - } - - AUnionType unionType = (AUnionType) type; - List<IAType> items = new ArrayList<>(); - // copy the item types - items.addAll(unionType.getUnionList()); - - // remove missing - for (int i = items.size() - 1; i >= 0; i--) { - IAType itemType = items.get(i); - if (itemType.getTypeTag() == ATypeTag.MISSING) { - items.remove(i); - } - } - if (items.size() == 1) { - //only one type is left - return items.get(0); - } else { - //more than two types are left - return new AUnionType(items, unionType.getTypeName()); - } - } -} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotUnknownTypeComputer.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotUnknownTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotUnknownTypeComputer.java new file mode 100644 index 0000000..163ff30 --- /dev/null +++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotUnknownTypeComputer.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.asterix.om.typecomputer.impl; + +import org.apache.asterix.om.typecomputer.base.IResultTypeComputer; +import org.apache.asterix.om.types.ATypeTag; +import org.apache.asterix.om.types.AUnionType; +import org.apache.asterix.om.types.IAType; +import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException; +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.metadata.IMetadataProvider; + +/** + * This class is the type computer for check-unknown function. + * If the input type is not a union, we just return it. + * If the input type is a union, we return the actual, non-null/non-missing type. + */ +public class NotUnknownTypeComputer implements IResultTypeComputer { + + public static final NotUnknownTypeComputer INSTANCE = new NotUnknownTypeComputer(); + + @Override + public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env, + IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException { + AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) expression; + IAType type = (IAType) env.getType(f.getArguments().get(0).getValue()); + if (type.getTypeTag() != ATypeTag.UNION) { + // directly return the input type if it is not a union + return type; + } + AUnionType unionType = (AUnionType) type; + return unionType.getActualType(); + } +} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullableDoubleTypeComputer.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullableDoubleTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullableDoubleTypeComputer.java index 94c75d2..be3138d 100644 --- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullableDoubleTypeComputer.java +++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullableDoubleTypeComputer.java @@ -37,6 +37,6 @@ public class NullableDoubleTypeComputer implements IResultTypeComputer { @Override public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env, IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException { - return AUnionType.createMissableType(BuiltinType.ADOUBLE, "OptionalDouble"); + return AUnionType.createNullableType(BuiltinType.ADOUBLE, "OptionalDouble"); } } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddFieldsTypeComputer.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddFieldsTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddFieldsTypeComputer.java index 289db7c..6d29c36 100644 --- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddFieldsTypeComputer.java +++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddFieldsTypeComputer.java @@ -40,7 +40,6 @@ import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException; import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression; import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag; import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression; -import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractLogicalExpression; import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment; import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider; @@ -56,7 +55,6 @@ public class RecordAddFieldsTypeComputer implements IResultTypeComputer { @Override public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env, IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException { - AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expression; IAType type0 = (IAType) env.getType(funcExpr.getArguments().get(0).getValue()); @@ -65,7 +63,7 @@ public class RecordAddFieldsTypeComputer implements IResultTypeComputer { throw new AlgebricksException("Input record cannot be null"); } - AbstractLogicalExpression arg1 = (AbstractLogicalExpression) funcExpr.getArguments().get(1).getValue(); + ILogicalExpression arg1 = funcExpr.getArguments().get(1).getValue(); IAType type1 = (IAType) env.getType(arg1); AOrderedListType inputOrderedListType = TypeComputeUtils.extractOrderedListType(type1); if (inputOrderedListType == null) { http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubsetCollectionTypeComputer.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubsetCollectionTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubsetCollectionTypeComputer.java index 40c57a4..3fcb9bb 100644 --- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubsetCollectionTypeComputer.java +++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubsetCollectionTypeComputer.java @@ -22,6 +22,7 @@ import org.apache.asterix.om.typecomputer.base.IResultTypeComputer; import org.apache.asterix.om.types.ATypeTag; import org.apache.asterix.om.types.AUnionType; import org.apache.asterix.om.types.AbstractCollectionType; +import org.apache.asterix.om.types.BuiltinType; import org.apache.asterix.om.types.IAType; import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException; import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression; @@ -65,6 +66,8 @@ public class SubsetCollectionTypeComputer implements IResultTypeComputer { } throw new AlgebricksException("Expecting collection type. Found " + t); } + case ANY: + return BuiltinType.ANY; default: { throw new AlgebricksException("Expecting collection type. Found " + t); } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java index 711b840..823f51e 100644 --- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java +++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java @@ -111,19 +111,27 @@ public class TypeComputeUtils { byte category = CERTAIN; boolean meetNull = false; for (IAType inputType : inputTypes) { - ATypeTag inputTypeTag = inputType.getTypeTag(); - if (inputTypeTag == ATypeTag.UNION) { - AUnionType unionType = (AUnionType) inputType; - if (unionType.isNullableType()) { + switch (inputType.getTypeTag()) { + case UNION: + AUnionType unionType = (AUnionType) inputType; + if (unionType.isNullableType()) { + category |= NULLABLE; + } + if (unionType.isMissableType()) { + category |= MISSABLE; + } + break; + case MISSING: + return MISSING; + case NULL: + meetNull = true; + break; + case ANY: category |= NULLABLE; - } - if (unionType.isMissableType()) { category |= MISSABLE; - } - } else if (inputTypeTag == ATypeTag.MISSING) { - return MISSING; - } else if (inputTypeTag == ATypeTag.NULL) { - meetNull = true; + break; + default: + break; } } if (meetNull) { @@ -133,6 +141,9 @@ public class TypeComputeUtils { } private static IAType getResultType(IAType type, byte category) { + if (type.getTypeTag() == ATypeTag.ANY) { + return type; + } if (category == CERTAIN) { return type; } @@ -185,6 +196,8 @@ public class TypeComputeUtils { } else { return null; } + case ANY: + return ARecordType.FULLY_OPEN_RECORD_TYPE; default: return null; } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/test/java/org/apache/asterix/om/typecomputer/TypeComputerTest.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-om/src/test/java/org/apache/asterix/om/typecomputer/TypeComputerTest.java b/asterixdb/asterix-om/src/test/java/org/apache/asterix/om/typecomputer/TypeComputerTest.java new file mode 100644 index 0000000..760fd18 --- /dev/null +++ b/asterixdb/asterix-om/src/test/java/org/apache/asterix/om/typecomputer/TypeComputerTest.java @@ -0,0 +1,116 @@ +/* + * 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.asterix.om.typecomputer; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.asterix.om.typecomputer.base.IResultTypeComputer; +import org.apache.asterix.om.types.ATypeTag; +import org.apache.asterix.om.types.AUnionType; +import org.apache.asterix.om.types.BuiltinType; +import org.apache.asterix.om.types.IAType; +import org.apache.commons.lang3.mutable.Mutable; +import org.apache.commons.lang3.mutable.MutableObject; +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.metadata.IMetadataProvider; +import org.junit.Assert; +import org.junit.Test; +import org.reflections.Reflections; +import org.reflections.scanners.SubTypesScanner; + +// Tests if all type computers can handle input type ANY properly. +public class TypeComputerTest { + + @Test + public void test() throws Exception { + // Several exceptional type computers. + Set<String> exceptionalTypeComputers = new HashSet<>(); + exceptionalTypeComputers.add("InjectFailureTypeComputer"); + exceptionalTypeComputers.add("RecordAddFieldsTypeComputer"); + exceptionalTypeComputers.add("OpenRecordConstructorResultType"); + exceptionalTypeComputers.add("RecordRemoveFieldsTypeComputer"); + exceptionalTypeComputers.add("ClosedRecordConstructorResultType"); + exceptionalTypeComputers.add("LocalAvgTypeComputer"); + exceptionalTypeComputers.add("BooleanOnlyTypeComputer"); + exceptionalTypeComputers.add("AMissingTypeComputer"); + exceptionalTypeComputers.add("NullableDoubleTypeComputer"); + exceptionalTypeComputers.add("RecordMergeTypeComputer"); + + // 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); + for (Class<? extends IResultTypeComputer> c : classes) { + if (exceptionalTypeComputers.contains(c.getSimpleName()) || Modifier.isAbstract(c.getModifiers())) { + continue; + } + System.out.println("Test type computer: " + c.getName()); + Assert.assertTrue(testTypeComputer(c)); + } + } + + private boolean testTypeComputer(Class<? extends IResultTypeComputer> c) throws Exception { + // Mocks the type environment. + IVariableTypeEnvironment mockTypeEnv = mock(IVariableTypeEnvironment.class); + // Mocks the metadata provider. + IMetadataProvider<?, ?> mockMetadataProvider = mock(IMetadataProvider.class); + + // Mocks function expression. + AbstractFunctionCallExpression mockExpr = mock(AbstractFunctionCallExpression.class); + + // A function at most has six argument. + List<Mutable<ILogicalExpression>> argRefs = new ArrayList<>(); + for (int argIndex = 0; argIndex < 6; ++argIndex) { + ILogicalExpression mockArg = mock(ILogicalExpression.class); + argRefs.add(new MutableObject<>(mockArg)); + when(mockTypeEnv.getType(mockArg)).thenReturn(BuiltinType.ANY); + } + + // Sets up arguments for the mocked expression. + when(mockExpr.getArguments()).thenReturn(argRefs); + + // Sets up required/actual types of the mocked expression. + Object[] opaqueParameters = new Object[2]; + opaqueParameters[0] = BuiltinType.ANY; + opaqueParameters[1] = BuiltinType.ANY; + when(mockExpr.getOpaqueParameters()).thenReturn(opaqueParameters); + + // Tests the return type. It should be either ANY or NULLABLE/MISSABLE. + IResultTypeComputer instance = (IResultTypeComputer) c.getField("INSTANCE").get(null); + IAType resultType = instance.computeType(mockExpr, mockTypeEnv, mockMetadataProvider); + ATypeTag typeTag = resultType.getTypeTag(); + if (typeTag == ATypeTag.ANY) { + return true; + } + if (typeTag == ATypeTag.UNION) { + AUnionType unionType = (AUnionType) resultType; + return unionType.isMissableType() && unionType.isNullableType(); + } + return false; + } +}