http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/test/java/org/apache/freemarker/core/model/impl/ParameterListPreferabilityTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/ParameterListPreferabilityTest.java b/src/test/java/org/apache/freemarker/core/model/impl/ParameterListPreferabilityTest.java new file mode 100644 index 0000000..2c22dc6 --- /dev/null +++ b/src/test/java/org/apache/freemarker/core/model/impl/ParameterListPreferabilityTest.java @@ -0,0 +1,445 @@ +/* + * 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.freemarker.core.model.impl; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.freemarker.core.util._NumberUtil; + +import junit.framework.TestCase; + +@SuppressWarnings("boxing") +public class ParameterListPreferabilityTest extends TestCase { + + public ParameterListPreferabilityTest(String name) { + super(name); + } + + public void testNumberical() { + // Note: the signature lists consists of the same elements, only their order changes depending on the type + // of the argument value. + + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { byte.class }, + new Class[] { Byte.class }, + new Class[] { short.class }, + new Class[] { Short.class }, + new Class[] { int.class }, + new Class[] { Integer.class }, + new Class[] { long.class }, + new Class[] { Long.class }, + new Class[] { BigInteger.class }, + new Class[] { float.class }, + new Class[] { Float.class }, + new Class[] { double.class }, + new Class[] { Double.class }, + new Class[] { BigDecimal.class }, + new Class[] { Number.class }, + new Class[] { Serializable.class }, + new Class[] { Object.class } + }, + new Object[] { (byte) 1 }); + + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { BigDecimal.class }, + new Class[] { BigInteger.class }, + new Class[] { int.class }, + new Class[] { Integer.class }, + new Class[] { long.class }, + new Class[] { Long.class }, + new Class[] { double.class }, + new Class[] { Double.class }, + new Class[] { float.class }, + new Class[] { Float.class }, + new Class[] { short.class }, + new Class[] { Short.class }, + new Class[] { byte.class }, + new Class[] { Byte.class }, + new Class[] { Number.class }, + new Class[] { Serializable.class }, + new Class[] { Object.class }, + }, + new Object[] { new OverloadedNumberUtil.IntegerBigDecimal(new BigDecimal("1")) }); + + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { BigDecimal.class }, + new Class[] { double.class }, + new Class[] { Double.class }, + new Class[] { float.class }, + new Class[] { Float.class }, + new Class[] { BigInteger.class }, + new Class[] { int.class }, + new Class[] { Integer.class }, + new Class[] { long.class }, + new Class[] { Long.class }, + new Class[] { short.class }, + new Class[] { Short.class }, + new Class[] { byte.class }, + new Class[] { Byte.class }, + new Class[] { Number.class }, + new Class[] { Serializable.class }, + new Class[] { Object.class }, + }, + new Object[] { new BigDecimal("1") /* possibly non-integer */ }); + + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { float.class }, + new Class[] { Float.class }, + new Class[] { double.class }, + new Class[] { Double.class }, + new Class[] { BigDecimal.class }, + new Class[] { int.class }, + new Class[] { Integer.class }, + new Class[] { long.class }, + new Class[] { Long.class }, + new Class[] { short.class }, + new Class[] { Short.class }, + new Class[] { byte.class }, + new Class[] { Byte.class }, + new Class[] { BigInteger.class }, + new Class[] { Number.class }, + new Class[] { Serializable.class }, + new Class[] { Object.class }, + }, + new Object[] { new OverloadedNumberUtil.FloatOrByte(1f, (byte) 1) }); + + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { int.class }, + new Class[] { Integer.class }, + new Class[] { long.class }, + new Class[] { Long.class }, + new Class[] { BigInteger.class }, + new Class[] { double.class }, + new Class[] { Double.class }, + new Class[] { BigDecimal.class }, + new Class[] { short.class }, + new Class[] { Short.class }, + new Class[] { float.class }, + new Class[] { Float.class }, + + // Two incompatibles removed, would be removed in reality: + new Class[] { byte.class }, + new Class[] { Byte.class }, + + new Class[] { Number.class }, + new Class[] { Serializable.class }, + new Class[] { Object.class } + }, + new Object[] { new OverloadedNumberUtil.IntegerOrShort(1, (short) 1) }); + + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { long.class }, + new Class[] { Long.class }, + new Class[] { BigInteger.class }, + new Class[] { BigDecimal.class }, + new Class[] { double.class }, + new Class[] { Double.class }, + new Class[] { float.class }, + new Class[] { Float.class }, + // skip byte and short as the would be equal with int (all invalid target types) + new Class[] { int.class }, // In reality, this and Integer are removed as not-applicable overloads + new Class[] { Integer.class }, + new Class[] { Number.class }, + new Class[] { Serializable.class }, + new Class[] { Object.class } + }, + new Object[] { 1L }); + + // Undecidable comparisons: + + testAllCmpPermutationsEqu( + new Class[][] { + new Class[] { Byte.class }, + new Class[] { Short.class }, + new Class[] { Integer.class }, + new Class[] { Long.class }, + new Class[] { BigInteger.class }, + new Class[] { Float.class }, + }, + new Object[] { 1.0 }); + + testAllCmpPermutationsEqu( + new Class[][] { + new Class[] { byte.class }, + new Class[] { short.class }, + new Class[] { int.class }, + new Class[] { long.class }, + new Class[] { float.class }, + }, + new Object[] { 1.0 }); + } + + public void testPrimitiveIsMoreSpecific() { + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { boolean.class }, + new Class[] { Boolean.class } + }, + new Object[] { true }); + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { char.class }, + new Class[] { Character.class } + }, + new Object[] { 'x' }); + } + + public void testCharIsMoreSpecificThanString() { + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { char.class }, + new Class[] { Character.class }, + new Class[] { String.class }, + new Class[] { CharSequence.class } + }, + new Object[] { "s" }); + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { char.class }, + new Class[] { Character.class }, + new Class[] { String.class } + }, + new Object[] { 'c' }); + } + + public void testClassHierarchy() { + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { LinkedHashMap.class }, + new Class[] { HashMap.class }, + new Class[] { Map.class }, + new Class[] { Object.class } + }, + new Object[] { new LinkedHashMap() }); + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { LinkedHashMap.class }, + new Class[] { Cloneable.class }, + new Class[] { Object.class } + }, + new Object[] { new LinkedHashMap() }); + } + + public void testNumericalWithNonNumerical() { + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { int.class }, + new Class[] { Integer.class }, + new Class[] { Comparable.class }, + new Class[] { Object.class }, + }, + new Object[] { 1 }); + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { int.class }, + new Class[] { Integer.class }, + new Class[] { char.class }, + new Class[] { Character.class }, + }, + new Object[] { 1 }); + } + + public void testUnrelated() { + testAllCmpPermutationsEqu( + new Class[][] { + new Class[] { Serializable.class }, + new Class[] { CharSequence.class }, + new Class[] { Comparable.class } + }, + new Object[] { "s" }); + + testAllCmpPermutationsEqu( + new Class[][] { + new Class[] { HashMap.class }, + new Class[] { TreeMap.class } + }, + new Object[] { null }); + } + + public void testMultiParameter() { + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { String.class, String.class, String.class }, + + new Class[] { String.class, String.class, Object.class }, + new Class[] { String.class, Object.class, String.class }, + new Class[] { Object.class, String.class, String.class }, + + new Class[] { String.class, Object.class, Object.class }, + new Class[] { Object.class, String.class, Object.class }, + new Class[] { Object.class, Object.class, String.class }, + + new Class[] { Object.class, Object.class, Object.class }, + }, + new Object[] { "a", "b", "c" }); + + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { String.class, String.class }, + new Class[] { String.class, Object.class }, + new Class[] { CharSequence.class, CharSequence.class }, + new Class[] { CharSequence.class, Object.class }, + new Class[] { Object.class, String.class }, + new Class[] { Object.class, CharSequence.class }, + new Class[] { Object.class, Object.class }, + }, + new Object[] { "a", "b" }); + + // Subclassing is more important than primitive-VS-boxed: + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { boolean.class, boolean.class, boolean.class, String.class }, + new Class[] { Boolean.class, boolean.class, boolean.class, String.class }, + new Class[] { boolean.class, Boolean.class, Boolean.class, String.class }, + new Class[] { Boolean.class, boolean.class, Boolean.class, String.class }, + new Class[] { Boolean.class, Boolean.class, boolean.class, String.class }, + new Class[] { Boolean.class, Boolean.class, Boolean.class, String.class }, + new Class[] { Boolean.class, Boolean.class, Boolean.class, CharSequence.class }, + new Class[] { boolean.class, boolean.class, boolean.class, Object.class }, + new Class[] { Boolean.class, boolean.class, boolean.class, Object.class }, + new Class[] { boolean.class, Boolean.class, Boolean.class, Object.class }, + new Class[] { Boolean.class, boolean.class, Boolean.class, Object.class }, + new Class[] { Boolean.class, Boolean.class, boolean.class, Object.class }, + new Class[] { Boolean.class, Boolean.class, Boolean.class, Object.class }, + }, + new Object[] { true, false, true, "a" }); + + // Subclassing is more important than primitive-VS-boxed: + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { int.class, int.class, int.class, String.class }, + new Class[] { Integer.class, int.class, int.class, String.class }, + new Class[] { int.class, Integer.class, Integer.class, String.class }, + new Class[] { Integer.class, int.class, Integer.class, String.class }, + new Class[] { Integer.class, Integer.class, int.class, String.class }, + new Class[] { Integer.class, Integer.class, Integer.class, String.class }, + new Class[] { Integer.class, Integer.class, Integer.class, CharSequence.class }, + new Class[] { int.class, int.class, int.class, Object.class }, + new Class[] { Integer.class, int.class, int.class, Object.class }, + new Class[] { int.class, Integer.class, Integer.class, Object.class }, + new Class[] { Integer.class, int.class, Integer.class, Object.class }, + new Class[] { Integer.class, Integer.class, int.class, Object.class }, + new Class[] { Integer.class, Integer.class, Integer.class, Object.class }, + }, + new Object[] { 1, 2, 3, "a" }); + } + + public void testVarargs() { + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { String.class, String[].class }, + new Class[] { String.class, CharSequence[].class }, + new Class[] { String.class, Object[].class }, + }, + new Object[] { "a", "b", "c" }, + true); + + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { String.class, int[].class }, + new Class[] { String.class, Integer[].class }, + new Class[] { String.class, long[].class }, + new Class[] { String.class, Long[].class }, + new Class[] { String.class, double[].class }, + new Class[] { String.class, Double[].class }, + new Class[] { String.class, Serializable[].class }, + new Class[] { String.class, Object[].class }, + }, + new Object[] { "a", 1, 2, 3 }, + true); + + // 0-long varargs list; in case of ambiguity, the varargs component type decides: + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { String.class, Object[].class }, + new Class[] { CharSequence.class, int[].class }, + new Class[] { CharSequence.class, Integer[].class }, + new Class[] { CharSequence.class, long[].class }, + new Class[] { CharSequence.class, Long[].class }, + new Class[] { CharSequence.class, double[].class }, + new Class[] { CharSequence.class, Double[].class }, + new Class[] { CharSequence.class, Serializable[].class }, + new Class[] { CharSequence.class, Object[].class }, + new Class[] { Object.class, int[].class }, + }, + new Object[] { "a" }, + true); + + + // Different oms prefix length; in the case of ambiguity, the one with higher oms param count wins. + testAllCmpPermutationsInc( + new Class[][] { + new Class[] { String.class, int.class, int.class, int[].class }, + new Class[] { String.class, int.class, int[].class }, + new Class[] { String.class, int[].class }, + }, + new Object[] { "a", 1, 2, 3 }, + true); + } + + private void testAllCmpPermutationsInc(Class[][] sortedSignatures, Object[] args) { + testAllCmpPermutationsInc(sortedSignatures, args, false); + } + + /** + * Compares all items with all other items in the provided descending sorted array of signatures, checking that + * for all valid indexes i and j, where j > i, it stands that sortedSignatures[i] > sortedSignatures[j]. + * The comparisons are done with both operand orders, also each items is compared to itself too. + * + * @param sortedSignatures method signatures sorted by decreasing specificity + */ + private void testAllCmpPermutationsInc(Class[][] sortedSignatures, Object[] args, boolean varargs) { + final ArgumentTypes argTs = new ArgumentTypes(args); + for (int i = 0; i < sortedSignatures.length; i++) { + for (int j = 0; j < sortedSignatures.length; j++) { + assertEquals("sortedSignatures[" + i + "] <==> sortedSignatures [" + j + "]", + _NumberUtil.getSignum( + Integer.valueOf(j).compareTo(i)), + _NumberUtil.getSignum( + argTs.compareParameterListPreferability( + sortedSignatures[i], sortedSignatures[j], varargs))); + } + } + } + + private void testAllCmpPermutationsEqu(Class[][] signatures, Object[] args) { + final ArgumentTypes argTs = new ArgumentTypes(args); + for (int i = 0; i < signatures.length; i++) { + for (int j = 0; j < signatures.length; j++) { + assertEquals("sortedSignatures[" + i + "] <==> sortedSignatures [" + j + "]", + 0, + argTs.compareParameterListPreferability(signatures[i], signatures[j], false)); + } + } + } + +}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/test/java/org/apache/freemarker/core/model/impl/PrallelObjectIntrospectionTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/PrallelObjectIntrospectionTest.java b/src/test/java/org/apache/freemarker/core/model/impl/PrallelObjectIntrospectionTest.java new file mode 100644 index 0000000..dadefba --- /dev/null +++ b/src/test/java/org/apache/freemarker/core/model/impl/PrallelObjectIntrospectionTest.java @@ -0,0 +1,43 @@ +/* + * 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.freemarker.core.model.impl; + +import org.apache.freemarker.core.model.TemplateHashModel; +import org.apache.freemarker.core.model.TemplateModelException; + +public class PrallelObjectIntrospectionTest extends AbstractParallelIntrospectionTest { + + public PrallelObjectIntrospectionTest(String name) { + super(name); + } + + public static void main(String[] args) { + new PrallelObjectIntrospectionTest("almostForever") + .testReliability(Integer.MAX_VALUE); + } + + @Override + protected TemplateHashModel getWrappedEntity(int objIdx) + throws TemplateModelException { + return (TemplateHashModel) getObjectWrapper().wrap( + ManyObjectsOfDifferentClasses.OBJECTS[objIdx]); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/test/java/org/apache/freemarker/core/model/impl/PrallelStaticIntrospectionTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/PrallelStaticIntrospectionTest.java b/src/test/java/org/apache/freemarker/core/model/impl/PrallelStaticIntrospectionTest.java new file mode 100644 index 0000000..0cac78a --- /dev/null +++ b/src/test/java/org/apache/freemarker/core/model/impl/PrallelStaticIntrospectionTest.java @@ -0,0 +1,47 @@ +/* + * 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.freemarker.core.model.impl; + +import org.apache.freemarker.core.model.TemplateHashModel; +import org.apache.freemarker.core.model.TemplateModelException; + +public class PrallelStaticIntrospectionTest extends AbstractParallelIntrospectionTest { + + private static final String STATICS_CLASS_CONTAINER_CLASS_NAME + = ManyStaticsOfDifferentClasses.class.getName(); + + public PrallelStaticIntrospectionTest(String name) { + super(name); + } + + public static void main(String[] args) { + new PrallelStaticIntrospectionTest("almostForever") + .testReliability(Integer.MAX_VALUE); + } + + @Override + protected TemplateHashModel getWrappedEntity(int clIdx) + throws TemplateModelException { + return (TemplateHashModel) getObjectWrapper().getStaticModels().get( + STATICS_CLASS_CONTAINER_CLASS_NAME + "$C" + + clIdx); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/test/java/org/apache/freemarker/core/model/impl/RationalNumber.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/RationalNumber.java b/src/test/java/org/apache/freemarker/core/model/impl/RationalNumber.java new file mode 100644 index 0000000..7359439 --- /dev/null +++ b/src/test/java/org/apache/freemarker/core/model/impl/RationalNumber.java @@ -0,0 +1,90 @@ +/* + * 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.freemarker.core.model.impl; + +public final class RationalNumber extends Number { + + final int divident; + final int divisor; + + public RationalNumber(int divident, int divisor) { + this.divident = divident; + this.divisor = divisor; + } + + @Override + public int intValue() { + return divident / divisor; + } + + @Override + public long longValue() { + return divident / (long) divisor; + } + + @Override + public float floatValue() { + return (float) (divident / (double) divisor); + } + + @Override + public double doubleValue() { + return divident / (double) divisor; + } + + public int getDivident() { + return divident; + } + + public int getDivisor() { + return divisor; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + divident; + result = prime * result + divisor; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RationalNumber other = (RationalNumber) obj; + if (divident != other.divident) + return false; + if (divisor != other.divisor) + return false; + return true; + } + + @Override + public String toString() { + return divident + "/" + divisor; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/test/java/org/apache/freemarker/core/model/impl/StaticModelsTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/StaticModelsTest.java b/src/test/java/org/apache/freemarker/core/model/impl/StaticModelsTest.java new file mode 100644 index 0000000..0287d6d --- /dev/null +++ b/src/test/java/org/apache/freemarker/core/model/impl/StaticModelsTest.java @@ -0,0 +1,90 @@ +/* + * 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.freemarker.core.model.impl; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.util.ArrayList; + +import org.apache.freemarker.core.Configuration; +import org.apache.freemarker.core.model.TemplateHashModel; +import org.apache.freemarker.core.model.TemplateMethodModelEx; +import org.apache.freemarker.core.model.TemplateModel; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.model.TemplateScalarModel; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class StaticModelsTest { + + @Test + public void modelCaching() throws Exception { + DefaultObjectWrapper ow = new DefaultObjectWrapper(Configuration.VERSION_3_0_0); + TemplateHashModel statics = ow.getStaticModels(); + TemplateHashModel s = (TemplateHashModel) statics.get(S.class.getName()); + assertNotNull(s); + assertNotNull(s.get("F")); + assertNotNull(s.get("m")); + try { + s.get("x"); + fail(); + } catch (TemplateModelException e) { + assertThat(e.getMessage(), containsString("No such key")); + } + + try { + statics.get("no.such.ClassExists"); + fail(); + } catch (TemplateModelException e) { + assertTrue(e.getCause() instanceof ClassNotFoundException); + } + + TemplateModel f = s.get("F"); + assertTrue(f instanceof TemplateScalarModel); + assertEquals(((TemplateScalarModel) f).getAsString(), "F OK"); + + TemplateModel m = s.get("m"); + assertTrue(m instanceof TemplateMethodModelEx); + assertEquals(((TemplateScalarModel) ((TemplateMethodModelEx) m).exec(new ArrayList())).getAsString(), "m OK"); + + assertSame(s, statics.get(S.class.getName())); + + ow.clearClassIntrospecitonCache(); + TemplateHashModel sAfterClean = (TemplateHashModel) statics.get(S.class.getName()); + assertNotSame(s, sAfterClean); + assertSame(sAfterClean, statics.get(S.class.getName())); + assertNotNull(sAfterClean.get("F")); + assertNotNull(sAfterClean.get("m")); + } + + public static class S { + + public static final String F = "F OK"; + + public static String m() { + return "m OK"; + } + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/test/java/org/apache/freemarker/core/model/impl/TypeFlagsTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/TypeFlagsTest.java b/src/test/java/org/apache/freemarker/core/model/impl/TypeFlagsTest.java new file mode 100644 index 0000000..856a69f --- /dev/null +++ b/src/test/java/org/apache/freemarker/core/model/impl/TypeFlagsTest.java @@ -0,0 +1,671 @@ +/* + * 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.freemarker.core.model.impl; + +import java.io.File; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.freemarker.core.Configuration; + +import junit.framework.TestCase; + +public class TypeFlagsTest extends TestCase { + + public TypeFlagsTest(String name) { + super(name); + } + + private final DefaultObjectWrapper ow = new DefaultObjectWrapper(Configuration.VERSION_3_0_0); + + public void testSingleNumType() { + checkTypeFlags(SingleNumTypeC.class, "mInt", + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.INTEGER | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER + | TypeFlags.ACCEPTS_STRING); + checkTypeFlags(SingleNumTypeC.class, "mLong", + TypeFlags.LONG | TypeFlags.ACCEPTS_NUMBER); + checkTypeFlags(SingleNumTypeC.class, "mShort", + TypeFlags.SHORT | TypeFlags.ACCEPTS_NUMBER); + checkTypeFlags(SingleNumTypeC.class, "mByte", + TypeFlags.BYTE | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.ACCEPTS_ANY_OBJECT); + checkTypeFlags(SingleNumTypeC.class, "mDouble", + TypeFlags.DOUBLE | TypeFlags.ACCEPTS_NUMBER); + checkTypeFlags(SingleNumTypeC.class, "mFloat", + TypeFlags.FLOAT | TypeFlags.ACCEPTS_NUMBER); + checkTypeFlags(SingleNumTypeC.class, "mUnknown", + TypeFlags.UNKNOWN_NUMERICAL_TYPE | TypeFlags.ACCEPTS_NUMBER); + + checkTypeFlags(SingleNumTypeC.class, "mVarParamCnt", + TypeFlags.BIG_DECIMAL | TypeFlags.ACCEPTS_NUMBER); + checkTypeFlags(SingleNumTypeC.class, "mVarParamCnt", + TypeFlags.BIG_INTEGER | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.ACCEPTS_NUMBER); + checkTypeFlags(SingleNumTypeC.class, "mVarParamCnt", + TypeFlags.DOUBLE | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.FLOAT | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER); + } + + static public class SingleNumTypeC { + public void mInt(int a1, String a2) { } + public void mInt(int a1, int a2) { } + public void mLong(long a1) { } + public void mLong(Long a1) { } + public void mShort(short a1) { } + public void mByte(byte a1, boolean a2) { } + public void mByte(byte a1, String a2) { } + public void mByte(byte a1, Object a2) { } + public void mDouble(double a1) { } + public void mFloat(float a1) { } + public void mUnknown(RationalNumber a1) { }; + + public void mVarParamCnt(BigDecimal a1) { } + public void mVarParamCnt(BigInteger a1, Double a2) { } + public void mVarParamCnt(Double a1, Float a2, Integer a3) { } + public void mVarParamCnt(Object a1, char a2, boolean a3, File a4, Map a5, Boolean a6) { } + public void mVarParamCnt(Long a1, int a2, short a3, byte a4, double a5, float a6) { } + } + + public void testMultipleNumTypes() { + checkTypeFlags(MultiNumTypeC.class, "m1", + TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT + | TypeFlags.BYTE | TypeFlags.DOUBLE | TypeFlags.INTEGER + | TypeFlags.ACCEPTS_NUMBER + ); + + checkTypeFlags(MultiNumTypeC.class, "m2", + TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT + | TypeFlags.SHORT | TypeFlags.LONG | TypeFlags.FLOAT + | TypeFlags.ACCEPTS_NUMBER | TypeFlags.CHARACTER + ); + + checkTypeFlags(MultiNumTypeC.class, "m3", + TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT + | TypeFlags.BIG_DECIMAL | TypeFlags.BIG_INTEGER + | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.BIG_INTEGER | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT + | TypeFlags.BIG_DECIMAL | TypeFlags.UNKNOWN_NUMERICAL_TYPE + | TypeFlags.ACCEPTS_NUMBER + ); + + checkTypeFlags(MultiNumTypeC.class, "m4", + TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.FLOAT | TypeFlags.ACCEPTS_NUMBER + | TypeFlags.CHARACTER + ); + + checkTypeFlags(MultiNumTypeC.class, "m5", + TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT + | TypeFlags.FLOAT | TypeFlags.DOUBLE | TypeFlags.ACCEPTS_NUMBER + ); + + checkTypeFlags(MultiNumTypeC.class, "m6", + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER + ); + assertSame(getTypeFlags(MultiNumTypeC.class, "m6", false, 2), OverloadedMethodsSubset.ALL_ZEROS_ARRAY); + assertSame(getTypeFlags(MultiNumTypeC.class, "m6", true, 2), OverloadedMethodsSubset.ALL_ZEROS_ARRAY); + assertSame(getTypeFlags(MultiNumTypeC.class, "m6", false, 3), OverloadedMethodsSubset.ALL_ZEROS_ARRAY); + assertSame(getTypeFlags(MultiNumTypeC.class, "m6", true, 3), OverloadedMethodsSubset.ALL_ZEROS_ARRAY); + checkTypeFlags(MultiNumTypeC.class, "m6", + TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.DOUBLE | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.DOUBLE | TypeFlags.ACCEPTS_NUMBER, + 0 + ); + } + + static public class MultiNumTypeC { + public void m1(byte a1) { }; + public void m1(int a1) { }; + public void m1(double a2) { }; + + public void m2(short a1) { }; + public void m2(long a1) { }; + public void m2(float a1) { }; + public void m2(char a1) { }; + + public void m3(BigInteger a1, BigInteger a2, BigDecimal a3) { }; + public void m3(BigDecimal a1, BigInteger a2, RationalNumber a3) { }; + + public void m4(float a1) { }; + public void m4(char a1) { }; + + public void m5(Float a1) { }; + public void m5(Double a1) { }; + public void m5(Enum a1) { }; + + public void m6(int a1) { }; + public void m6(File a1, Throwable a2) { }; + public void m6(File a1, Throwable a2, StringBuilder a3) { }; + public void m6(File a1, Throwable a2, Throwable a3) { }; + public void m6(double a1, int a2, File a3, File a4) { }; + public void m6(File a1, int a2, double a3, File a4) { }; + } + + public void testVarargsNums() { + checkTypeFlags(VarArgsC.class, "m1", + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER + ); + checkTypeFlags(VarArgsC.class, "m2", + TypeFlags.DOUBLE | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER + ); + + checkTypeFlags(VarArgsC.class, "m3", + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER + ); + checkTypeFlags(VarArgsC.class, "m3", + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.INTEGER + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER + ); + checkTypeFlags(VarArgsC.class, "m3", + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.INTEGER + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.INTEGER + | TypeFlags.BIG_DECIMAL | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER + ); + + checkTypeFlags(VarArgsC.class, "m4", + TypeFlags.INTEGER | TypeFlags.LONG + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER + ); + + checkTypeFlags(VarArgsC.class, "m5", + TypeFlags.LONG | TypeFlags.ACCEPTS_NUMBER + ); + + checkTypeFlags(VarArgsC.class, "m6", + TypeFlags.LONG | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER + | TypeFlags.ACCEPTS_STRING + ); + + checkTypeFlags(VarArgsC.class, "m7", + TypeFlags.INTEGER | TypeFlags.BYTE + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.FLOAT + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER + ); + + checkTypeFlags(VarArgsC.class, "m8", + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.FLOAT + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER + ); + + checkTypeFlags(VarArgsC.class, "m9", + TypeFlags.INTEGER | TypeFlags.BYTE + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.ACCEPTS_NUMBER + ); + + checkTypeFlags(VarArgsC.class, "m10", + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.ACCEPTS_NUMBER + ); + checkTypeFlags(VarArgsC.class, "m10", + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.LONG | TypeFlags.DOUBLE + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER + ); + + checkTypeFlags(VarArgsC.class, "m11", + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.SHORT | TypeFlags.ACCEPTS_NUMBER + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER + ); + checkTypeFlags(VarArgsC.class, "m11", + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.SHORT + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.LONG | TypeFlags.DOUBLE + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER + ); + + checkTypeFlags(VarArgsC.class, "m12", + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.ACCEPTS_NUMBER + ); + checkTypeFlags(VarArgsC.class, "m12", + TypeFlags.INTEGER | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.SHORT + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.BYTE + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.LONG | TypeFlags.DOUBLE + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER + ); + + checkTypeFlags(VarArgsC.class, "m13", + TypeFlags.CHARACTER, + TypeFlags.DOUBLE | TypeFlags.ACCEPTS_NUMBER); + checkTypeFlags(VarArgsC.class, "m13", + TypeFlags.CHARACTER, + TypeFlags.DOUBLE | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.UNKNOWN_NUMERICAL_TYPE + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER, + TypeFlags.DOUBLE | TypeFlags.LONG + | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT | TypeFlags.ACCEPTS_NUMBER + ); + } + + static public class VarArgsC { + public void m1(int... va) { } + + public void m2(double a1, int... va) { } + + public void m3(int... va) { } + public void m3(int a1, double... va) { } + public void m3(int a1, double a2, BigDecimal... va) { } + + public void m4(int... va) { } + public void m4(long... va) { } + + public void m5(Long... va) { } + public void m5(long... va) { } + + public void m6(long... va) { } + public void m6(String... va) { } + + public void m7(int a1, double... va) { } + public void m7(byte a1, float... va) { } + + public void m8(int a1, double... va) { } + public void m8(int a1, float... va) { } + + public void m9(int a1, double... va) { } + public void m9(byte a1, double... va) { } + + public void m10(int a1, double a2, long... va) { } + public void m10(int a1, double... va) { } + + public void m11(int a1, short a2, long... va) { } + public void m11(int a1, double... va) { } + + public void m12(int a1, short a2, byte a3, long... va) { } + public void m12(int a1, double... va) { } + + public void m13(char a1, double a2, RationalNumber a3, Long... va) { } + public void m13(char a1, Double... va) { } + } + + public void testAllZeros() { + for (boolean reverse : new boolean[] { true, false }) { + assertSame(OverloadedMethodsSubset.ALL_ZEROS_ARRAY, getTypeFlags(AllZeroC.class, "m1", reverse, 0)); + assertSame(OverloadedMethodsSubset.ALL_ZEROS_ARRAY, getTypeFlags(AllZeroC.class, "m2", reverse, 2)); + assertSame(OverloadedMethodsSubset.ALL_ZEROS_ARRAY, getTypeFlags(AllZeroC.class, "m3", reverse, 1)); + } + } + + static public class AllZeroC { + public void m1() {} + + public void m2(File a1, File a2) {} + + public void m3(File a1) {} + public void m3(StringBuilder a1) {} + } + + public void testAcceptanceNonOverloaded() { + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber1", TypeFlags.ACCEPTS_NUMBER | TypeFlags.UNKNOWN_NUMERICAL_TYPE); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber2", TypeFlags.ACCEPTS_NUMBER | TypeFlags.BYTE); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber3", TypeFlags.ACCEPTS_NUMBER | TypeFlags.BYTE); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber4", TypeFlags.ACCEPTS_NUMBER | TypeFlags.SHORT); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber5", TypeFlags.ACCEPTS_NUMBER | TypeFlags.SHORT); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber6", TypeFlags.ACCEPTS_NUMBER | TypeFlags.INTEGER); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber7", TypeFlags.ACCEPTS_NUMBER | TypeFlags.INTEGER); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber8", TypeFlags.ACCEPTS_NUMBER | TypeFlags.LONG); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber9", TypeFlags.ACCEPTS_NUMBER | TypeFlags.LONG); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber10", TypeFlags.ACCEPTS_NUMBER | TypeFlags.FLOAT); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber11", TypeFlags.ACCEPTS_NUMBER | TypeFlags.FLOAT); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber12", TypeFlags.ACCEPTS_NUMBER | TypeFlags.DOUBLE); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber13", TypeFlags.ACCEPTS_NUMBER | TypeFlags.DOUBLE); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber14", TypeFlags.ACCEPTS_NUMBER | TypeFlags.BIG_INTEGER); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber15", TypeFlags.ACCEPTS_NUMBER | TypeFlags.BIG_DECIMAL); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mNumber16", TypeFlags.ACCEPTS_NUMBER | TypeFlags.UNKNOWN_NUMERICAL_TYPE); + + checkTypeFlags(AcceptanceNonoverloadedC.class, "mDate", TypeFlags.ACCEPTS_DATE); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mSQLDate1", 0); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mSQLDate2", 0); + + checkTypeFlags(AcceptanceNonoverloadedC.class, "mString", TypeFlags.ACCEPTS_STRING); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mCharSequence", TypeFlags.ACCEPTS_STRING); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mStringBuilder", 0); + + checkTypeFlags(AcceptanceNonoverloadedC.class, "mBool", TypeFlags.ACCEPTS_BOOLEAN); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mBoolean", TypeFlags.ACCEPTS_BOOLEAN); + + checkTypeFlags(AcceptanceNonoverloadedC.class, "mMap1", TypeFlags.ACCEPTS_MAP); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mMap2", 0); + + checkTypeFlags(AcceptanceNonoverloadedC.class, "mList1", TypeFlags.ACCEPTS_LIST); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mList2", 0); + + checkTypeFlags(AcceptanceNonoverloadedC.class, "mSet1", TypeFlags.ACCEPTS_SET); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mSet2", 0); + + checkTypeFlags(AcceptanceNonoverloadedC.class, "mCollection", TypeFlags.ACCEPTS_SET | TypeFlags.ACCEPTS_LIST); + + checkTypeFlags(AcceptanceNonoverloadedC.class, "mChar1", TypeFlags.CHARACTER); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mChar2", TypeFlags.CHARACTER); + + checkTypeFlags(AcceptanceNonoverloadedC.class, "mArray1", TypeFlags.ACCEPTS_ARRAY); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mArray2", TypeFlags.ACCEPTS_ARRAY); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mArray3", TypeFlags.ACCEPTS_ARRAY); + checkTypeFlags(AcceptanceNonoverloadedC.class, "mArray4", TypeFlags.ACCEPTS_ARRAY); + + checkTypeFlags(AcceptanceNonoverloadedC.class, "mObject", TypeFlags.ACCEPTS_ANY_OBJECT); + assertTrue((TypeFlags.ACCEPTS_ANY_OBJECT & TypeFlags.ACCEPTS_NUMBER) != 0); + assertTrue((TypeFlags.ACCEPTS_ANY_OBJECT & TypeFlags.ACCEPTS_STRING) != 0); + assertTrue((TypeFlags.ACCEPTS_ANY_OBJECT & TypeFlags.ACCEPTS_BOOLEAN) != 0); + assertTrue((TypeFlags.ACCEPTS_ANY_OBJECT & TypeFlags.ACCEPTS_MAP) != 0); + assertTrue((TypeFlags.ACCEPTS_ANY_OBJECT & TypeFlags.ACCEPTS_LIST) != 0); + assertTrue((TypeFlags.ACCEPTS_ANY_OBJECT & TypeFlags.ACCEPTS_SET) != 0); + assertTrue((TypeFlags.ACCEPTS_ANY_OBJECT & TypeFlags.ACCEPTS_ARRAY) != 0); + assertTrue((TypeFlags.ACCEPTS_ANY_OBJECT & TypeFlags.CHARACTER) == 0); // deliberatly 0 + + checkTypeFlags(AcceptanceNonoverloadedC.class, "mMapDate", 0); + + checkTypeFlags(AcceptanceNonoverloadedC.class, "mDateBooleanList", + TypeFlags.ACCEPTS_DATE, TypeFlags.ACCEPTS_BOOLEAN, TypeFlags.ACCEPTS_LIST); + } + + static public class AcceptanceNonoverloadedC { + public void mNumber1(Number a1) {} + public void mNumber2(Byte a1) {} + public void mNumber3(byte a1) {} + public void mNumber4(Short a1) {} + public void mNumber5(short a1) {} + public void mNumber6(Integer a1) {} + public void mNumber7(int a1) {} + public void mNumber8(Long a1) {} + public void mNumber9(long a1) {} + public void mNumber10(Float a1) {} + public void mNumber11(float a1) {} + public void mNumber12(Double a1) {} + public void mNumber13(double a1) {} + public void mNumber14(BigInteger a1) {} + public void mNumber15(BigDecimal a1) {} + public void mNumber16(RationalNumber a1) {} + + public void mDate(Date a1) {} + public void mSQLDate1(java.sql.Date a1) {} + public void mSQLDate2(java.sql.Timestamp a1) {} + + public void mString(String a1) {} + public void mCharSequence(CharSequence a1) {} + public void mStringBuilder(StringBuilder a1) {} + + public void mBool(boolean a1) {} + public void mBoolean(Boolean a1) {} + + public void mMap1(Map a1) {} + public void mMap2(LinkedHashMap a1) {} + + public void mList1(List a1) {} + public void mList2(ArrayList a1) {} + + public void mSet1(Set a1) {} + public void mSet2(HashSet a1) {} + + public void mCollection(Collection a1) {} + + public void mMapDate(MapDate a1) {} + + public void mChar1(Character a1) {} + public void mChar2(char a1) {} + + public void mArray1(Object[] a1) {} + public void mArray2(int[] a1) {} + public void mArray3(Integer[] a1) {} + public void mArray4(Void[] a1) {} + + public void mObject(Object a1) {} + + public void mDateBooleanList(Date a1, boolean a2, List a3) {} + } + + public void testAcceptanceOverloaded() { + checkTypeFlags(AcceptanceOverloadedC.class, "mLongDateList", + TypeFlags.ACCEPTS_NUMBER | TypeFlags.LONG | TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT + | TypeFlags.ACCEPTS_DATE | TypeFlags.ACCEPTS_LIST); + checkTypeFlags(AcceptanceOverloadedC.class, "mBoolean", TypeFlags.ACCEPTS_BOOLEAN); + checkTypeFlags(AcceptanceOverloadedC.class, "mStringChar", + TypeFlags.ACCEPTS_STRING | TypeFlags.CHARACTER); + checkTypeFlags(AcceptanceOverloadedC.class, "mStringFile", TypeFlags.ACCEPTS_STRING); + checkTypeFlags(AcceptanceOverloadedC.class, "mMapObject", TypeFlags.ACCEPTS_ANY_OBJECT); + checkTypeFlags(AcceptanceOverloadedC.class, "mSetMap", TypeFlags.ACCEPTS_MAP | TypeFlags.ACCEPTS_SET); + checkTypeFlags(AcceptanceOverloadedC.class, "mCollectionMap", + TypeFlags.ACCEPTS_MAP | TypeFlags.ACCEPTS_SET | TypeFlags.ACCEPTS_LIST); + checkTypeFlags(AcceptanceOverloadedC.class, "mArray", TypeFlags.ACCEPTS_ARRAY); + checkTypeFlags(AcceptanceOverloadedC.class, "mArrayList", TypeFlags.ACCEPTS_ARRAY | TypeFlags.ACCEPTS_LIST); + + checkTypeFlags(AcceptanceOverloadedC.class, "mStringCollectionThenBooleanThenMapList", + TypeFlags.ACCEPTS_STRING | TypeFlags.ACCEPTS_LIST | TypeFlags.ACCEPTS_SET, + TypeFlags.ACCEPTS_BOOLEAN, + TypeFlags.ACCEPTS_MAP | TypeFlags.ACCEPTS_LIST); + } + + static public class AcceptanceOverloadedC { + public void mLongDateList(long a1) {} + public void mLongDateList(Date a1) {} + public void mLongDateList(List a1) {} + + public void mBoolean(boolean a1) {} + public void mBoolean(Boolean a1) {} + + public void mDate(Date a1) {} + public void mDate(java.sql.Date a1) {} + public void mDate(java.sql.Timestamp a1) {} + + public void mStringChar(String a1) {} + public void mStringChar(char a1) {} + public void mStringChar(Character a1) {} + + public void mStringFile(String a1) {} + public void mStringFile(File a1) {} + + public void mMapObject(Map a1) {} + public void mMapObject(Object a1) {} + + public void mSetMap(Set a1) {} + public void mSetMap(Map a1) {} + + public void mCollectionMap(Collection a1) {} + public void mCollectionMap(Map a1) {} + + public void mArray(Object[] a1) {} + public void mArray(int[] a1) {} + public void mArray(Integer[] a1) {} + public void mArray(Void[] a1) {} + + public void mArrayList(String[] a1) {} + public void mArrayList(List a1) {} + + public void mStringCollectionThenBooleanThenMapList(String a1, boolean a2, Map a3) {} + public void mStringCollectionThenBooleanThenMapList(Collection a1, boolean a2, Map a3) {} + public void mStringCollectionThenBooleanThenMapList(String a1, boolean a2, List a3) {} + } + + public void testAcceptanceVarargsC() { + checkTypeFlags(AcceptanceVarArgsC.class, "m1", + TypeFlags.ACCEPTS_LIST | TypeFlags.ACCEPTS_STRING); + + checkTypeFlags(AcceptanceVarArgsC.class, "m2", + TypeFlags.ACCEPTS_MAP, + TypeFlags.ACCEPTS_MAP | TypeFlags.ACCEPTS_STRING | TypeFlags.ACCEPTS_BOOLEAN, + TypeFlags.ACCEPTS_MAP | TypeFlags.ACCEPTS_STRING); + checkTypeFlags(AcceptanceVarArgsC.class, "m2", + TypeFlags.ACCEPTS_MAP, + TypeFlags.ACCEPTS_MAP | TypeFlags.ACCEPTS_STRING | TypeFlags.ACCEPTS_BOOLEAN); + checkTypeFlags(AcceptanceVarArgsC.class, "m2", + TypeFlags.ACCEPTS_MAP); + + checkTypeFlags(AcceptanceVarArgsC.class, "m3", + TypeFlags.ACCEPTS_BOOLEAN); + checkTypeFlags(AcceptanceVarArgsC.class, "m3", + TypeFlags.ACCEPTS_BOOLEAN | TypeFlags.ACCEPTS_STRING, + TypeFlags.ACCEPTS_BOOLEAN | TypeFlags.ACCEPTS_MAP, + TypeFlags.ACCEPTS_BOOLEAN | TypeFlags.CHARACTER, + TypeFlags.ACCEPTS_BOOLEAN); + } + + static public class AcceptanceVarArgsC { + public void m1(List... a1) {} + public void m1(String... a1) {} + + public void m2(Map a1, String... a2) {} + public void m2(Map a1, boolean a2, String... a3) {} + public void m2(Map... a1) {} + + public void m3(String a1, Map a2, char a3, Boolean... a4) {} + public void m3(boolean... a1) {} + } + + static public class MapDate extends Date implements Map { + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean containsKey(Object key) { + return false; + } + + @Override + public boolean containsValue(Object value) { + return false; + } + + @Override + public Object get(Object key) { + return null; + } + + @Override + public Object put(Object key, Object value) { + return null; + } + + @Override + public Object remove(Object key) { + return null; + } + + @Override + public void putAll(Map m) { + } + + @Override + public void clear() { + } + + @Override + public Set keySet() { + return null; + } + + @Override + public Collection values() { + return null; + } + + @Override + public Set entrySet() { + return null; + } + + } + + private OverloadedMethodsSubset newOverloadedMethodsSubset(Class cl, String methodName, final boolean desc) { + final Method[] ms = cl.getMethods(); + + final List<Method> filteredMethods = new ArrayList(); + for (Method m : ms) { + if (m.getName().equals(methodName)) { + filteredMethods.add(m); + } + } + // As the order in which getMethods() returns the methods is undefined, we sort them for test predictability: + Collections.sort(filteredMethods, new Comparator<Method>() { + @Override + public int compare(Method o1, Method o2) { + int res = o1.toString().compareTo(o2.toString()); + return desc ? -res : res; + } + }); + + final OverloadedMethodsSubset oms = cl.getName().indexOf("VarArgs") == -1 + ? new OverloadedFixArgsMethods() : new OverloadedVarArgsMethods(); + for (Method m : filteredMethods) { + oms.addCallableMemberDescriptor(new ReflectionCallableMemberDescriptor(m, m.getParameterTypes())); + } + return oms; + } + + private void checkTypeFlags(Class cl, String methodName, int... expectedTypeFlags) { + checkTypeFlags(cl, methodName, false, expectedTypeFlags); + checkTypeFlags(cl, methodName, true, expectedTypeFlags); + } + + private void checkTypeFlags(Class cl, String methodName, boolean revMetOrder, int... expectedTypeFlags) { + int[] actualParamTypes = getTypeFlags(cl, methodName, revMetOrder, expectedTypeFlags.length); + assertNotNull("Method " + methodName + "(#" + expectedTypeFlags.length + ") doesn't exist", actualParamTypes); + if (actualParamTypes != OverloadedMethodsSubset.ALL_ZEROS_ARRAY) { + assertEquals(expectedTypeFlags.length, actualParamTypes.length); + for (int i = 0; i < expectedTypeFlags.length; i++) { + assertEquals(expectedTypeFlags[i], actualParamTypes[i]); + } + } else { + for (int expectedTypeFlag : expectedTypeFlags) { + assertEquals(expectedTypeFlag, 0); + } + } + } + + private int[] getTypeFlags(Class cl, String methodName, boolean revMetOrder, int paramCnt) { + OverloadedMethodsSubset oms = newOverloadedMethodsSubset(cl, methodName, revMetOrder); + int[] actualParamTypes = oms.getTypeFlags(paramCnt); + return actualParamTypes; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/test/java/org/apache/freemarker/core/model/impl/beans/AbstractParallelIntrospectionTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/beans/AbstractParallelIntrospectionTest.java b/src/test/java/org/apache/freemarker/core/model/impl/beans/AbstractParallelIntrospectionTest.java deleted file mode 100644 index 62c4251..0000000 --- a/src/test/java/org/apache/freemarker/core/model/impl/beans/AbstractParallelIntrospectionTest.java +++ /dev/null @@ -1,125 +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.freemarker.core.model.impl.beans; - -import org.apache.freemarker.core.Configuration; -import org.apache.freemarker.core.model.TemplateHashModel; -import org.apache.freemarker.core.model.TemplateMethodModel; -import org.apache.freemarker.core.model.TemplateModelException; -import org.apache.freemarker.core.model.TemplateNumberModel; - -import junit.framework.TestCase; - -public abstract class AbstractParallelIntrospectionTest extends TestCase { - - private static final int NUM_THREADS = 8; - private static final int NUM_ENTITYES = 8; - private static final int NUM_MEMBERS = 8; - private static final int ITERATIONS = 20000; - private static final double CACHE_CLEARING_CHANCE = 0.01; - - private BeansWrapper beansWrapper = new BeansWrapper(Configuration.VERSION_3_0_0); - - public AbstractParallelIntrospectionTest(String name) { - super(name); - } - - public void testReliability() { - testReliability(ITERATIONS); - } - - public void testReliability(int iterations) { - TestThread[] ts = new TestThread[NUM_THREADS]; - for (int i = 0; i < NUM_THREADS; i++) { - ts[i] = new TestThread(iterations); - ts[i].start(); - } - - for (int i = 0; i < NUM_THREADS; i++) { - try { - ts[i].join(); - if (ts[i].error != null) { - throw new AssertionError(ts[i].error); - } - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - } - - protected abstract TemplateHashModel getWrappedEntity(int objIdx) throws TemplateModelException; - - protected final BeansWrapper getBeansWrapper() { - return beansWrapper; - } - - private class TestThread extends Thread { - - private final int iterations; - - private Throwable error; - - private TestThread(int iterations) { - this.iterations = iterations; - } - - @Override - public void run() { - try { - for (int i = 0; i < iterations; i++) { - if (Math.random() < CACHE_CLEARING_CHANCE) { - beansWrapper.clearClassIntrospecitonCache(); - } - int objIdx = (int) (Math.random() * NUM_ENTITYES); - TemplateHashModel h = getWrappedEntity(objIdx); - int mIdx = (int) (Math.random() * NUM_MEMBERS); - testProperty(h, objIdx, mIdx); - testMethod(h, objIdx, mIdx); - } - } catch (Throwable e) { - error = e; - } - } - - private void testProperty(TemplateHashModel h, int objIdx, int mIdx) - throws TemplateModelException, AssertionError { - TemplateNumberModel pv = (TemplateNumberModel) h.get("p" + mIdx); - final int expected = objIdx * 1000 + mIdx; - final int got = pv.getAsNumber().intValue(); - if (got != expected) { - throw new AssertionError("Property assertation failed; " + - "expected " + expected + ", but got " + got); - } - } - - private void testMethod(TemplateHashModel h, int objIdx, int mIdx) - throws TemplateModelException, AssertionError { - TemplateMethodModel pv = (TemplateMethodModel) h.get("m" + mIdx); - final int expected = objIdx * 1000 + mIdx; - final int got = ((TemplateNumberModel) pv.exec(null)).getAsNumber().intValue(); - if (got != expected) { - throw new AssertionError("Method assertation failed; " + - "expected " + expected + ", but got " + got); - } - } - - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/test/java/org/apache/freemarker/core/model/impl/beans/AlphabeticalMethodSorter.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/beans/AlphabeticalMethodSorter.java b/src/test/java/org/apache/freemarker/core/model/impl/beans/AlphabeticalMethodSorter.java deleted file mode 100644 index 57611f1..0000000 --- a/src/test/java/org/apache/freemarker/core/model/impl/beans/AlphabeticalMethodSorter.java +++ /dev/null @@ -1,49 +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.freemarker.core.model.impl.beans; - -import java.beans.MethodDescriptor; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; - -class AlphabeticalMethodSorter implements MethodSorter { - - private final boolean desc; - - public AlphabeticalMethodSorter(boolean desc) { - this.desc = desc; - } - - @Override - public MethodDescriptor[] sortMethodDescriptors(MethodDescriptor[] methodDescriptors) { - ArrayList<MethodDescriptor> ls = new ArrayList<>(Arrays.asList(methodDescriptors)); - Collections.sort(ls, new Comparator<MethodDescriptor>() { - @Override - public int compare(MethodDescriptor o1, MethodDescriptor o2) { - int res = o1.getMethod().toString().compareTo(o2.getMethod().toString()); - return desc ? -res : res; - } - }); - return ls.toArray(new MethodDescriptor[ls.size()]); - } - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansAPINewInstanceTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansAPINewInstanceTest.java b/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansAPINewInstanceTest.java deleted file mode 100644 index 34e2a4f..0000000 --- a/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansAPINewInstanceTest.java +++ /dev/null @@ -1,134 +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.freemarker.core.model.impl.beans; - -import org.apache.freemarker.core.Configuration; -import org.apache.freemarker.test.util.TestUtil; - -import junit.framework.TestCase; - -public class BeansAPINewInstanceTest extends TestCase { - - private BeansWrapper beansWrapper = new BeansWrapperBuilder(Configuration.VERSION_3_0_0).build(); - - public BeansAPINewInstanceTest(String name) { - super(name); - } - - @SuppressWarnings("boxing") - public void test() throws Exception { - testClassConstructors(""); - testClassConstructors("int... [1]", 1); - testClassConstructors("int 1, int 2", 1, 2); - testClassConstructors("int... [1, 2, 3]", 1, 2, 3); - testClassConstructors("int... [1, 2, 3]", 1, (byte) 2, (short) 3); - try { - testClassConstructors("int... [1, 2, 3]", 1, 2, (long) 3); - fail(); - } catch (NoSuchMethodException e) { - // Expected - } - - testClassConstructors("int 1, int 2", (byte) 1, (short) 2); - testClassConstructors("double 1.0, double 2.0", (long) 1, (short) 2); - testClassConstructors("double 1.0, double 2.0", 1, 2f); - testClassConstructors("Integer null, Integer null", null, null); - testClassConstructors("Integer null, Integer 1", null, 1); - testClassConstructors("int 1, String s", 1, "s"); - testClassConstructors("int 1, String null", 1, null); - testClassConstructors("Object null, Object s", null, "s"); - testClassConstructors("Object 1.0, Object s", 1f, "s"); - - testClassConstructors("Object s, int... [1, 2]", "s", 1, 2); - testClassConstructors("Object s, int... []", "s"); - - testClassConstructors2("int 1, int 2", (byte) 1, (short) 2); - try { - testClassConstructors2("int 1, int 2", 1, 2L); - fail(); - } catch (NoSuchMethodException e) { - // Expected - } - try { - testClassConstructors2("", "", ""); - fail(); - } catch (NoSuchMethodException e) { - // Expected - } - try { - testClassConstructors2("int 1", 1); - fail(); - } catch (NoSuchMethodException e) { - // Expected - } - try { - testClassConstructors2(""); - fail(); - } catch (NoSuchMethodException e) { - // Expected - } - } - - private void testClassConstructors(String expected, Object... args) throws Exception { - testCall(expected, Constructors.class, args); - } - - private void testClassConstructors2(String expected, Object... args) throws Exception { - testCall(expected, Constructors2.class, args); - } - - private void testCall(String expected, Class cl, Object... args) throws Exception { - Object obj = _BeansAPI.newInstance(cl, args, beansWrapper); - assertEquals(expected, obj.toString()); - } - - public static class Constructors { - private final String s; - - public Constructors() { s = ""; } - - public Constructors(int x, int y) { s = "int " + x + ", int " + y; } - public Constructors(int x, String y) { s = "int " + x + ", String " + y; } - public Constructors(int x, long y) { s = "int " + x + ", long " + y; } - public Constructors(double x, double y) { s = "double " + x + ", double " + y; } - public Constructors(Integer x, Integer y) { s = "Integer " + x + ", Integer " + y; } - public Constructors(Object x, Object y) { s = "Object " + x + ", Object " + y; } - - public Constructors(int... xs) { s = "int... " + TestUtil.arrayToString(xs); } - public Constructors(Object x, int... ys) { s = "Object " + x + ", int... " + TestUtil.arrayToString(ys); } - - @Override - public String toString() { - return s; - } - } - - public static class Constructors2 { - private final String s; - - public Constructors2(int x, int y) { s = "int " + x + ", int " + y; } - - @Override - public String toString() { - return s; - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperBasics.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperBasics.java b/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperBasics.java deleted file mode 100644 index bc6b8d7..0000000 --- a/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperBasics.java +++ /dev/null @@ -1,62 +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.freemarker.core.model.impl.beans; - -import static org.junit.Assert.*; - -import org.apache.freemarker.core.Configuration; -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateModelException; -import org.apache.freemarker.core.model.TemplateModelWithAPISupport; -import org.junit.Test; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; - -public class BeansWrapperBasics { - - @SuppressWarnings("boxing") - @Test - public void testAPIBuiltInSupport() throws TemplateModelException { - { - BeansWrapper bw = new BeansWrapperBuilder(Configuration.VERSION_3_0_0).build(); - assertWrappingResult(StringModel.class, bw.wrap("s")); - assertWrappingResult(NumberModel.class, bw.wrap(1.5)); - assertWrappingResult(BooleanModel.class, bw.wrap(true)); - assertWrappingResult(CollectionModel.class, bw.wrap(ImmutableList.of(1))); - assertWrappingResult(MapModel.class, bw.wrap(ImmutableMap.of("a", 1))); - } - - { - BeansWrapperBuilder bwb = new BeansWrapperBuilder(Configuration.VERSION_3_0_0); - bwb.setSimpleMapWrapper(true); - BeansWrapper bw = bwb.build(); - assertWrappingResult(SimpleMapModel.class, bw.wrap(ImmutableMap.of("a", 1))); - } - } - - private void assertWrappingResult(Class<? extends TemplateModel> expectedClass, TemplateModel tm) - throws TemplateModelException { - assertTrue(expectedClass.isInstance(tm)); - // All BeansWrapper products support `?api`: - assertTrue(((TemplateModelWithAPISupport) tm).getAPI() instanceof APIModel); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperCachesTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperCachesTest.java b/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperCachesTest.java deleted file mode 100644 index 8221a36..0000000 --- a/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperCachesTest.java +++ /dev/null @@ -1,99 +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.freemarker.core.model.impl.beans; - -import static org.junit.Assert.*; - -import java.lang.ref.Reference; - -import org.apache.freemarker.core.Configuration; -import org.apache.freemarker.core.model.impl.beans.BeansWrapper.MethodAppearanceDecision; -import org.apache.freemarker.core.model.impl.beans.BeansWrapper.MethodAppearanceDecisionInput; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class BeansWrapperCachesTest { - - @Test - public void introspectionSettingChanges() { - BeansWrapper bw = new BeansWrapper(Configuration.VERSION_3_0_0); - ClassIntrospector ci1 = bw.getClassIntrospector(); - checkRegisteredModelFactories(ci1, bw.getStaticModels(), bw.getEnumModels(), bw.getModelCache()); - - bw.setExposeFields(true); - ClassIntrospector ci2 = bw.getClassIntrospector(); - assertNotSame(ci1, ci2); - checkRegisteredModelFactories(ci1); - checkRegisteredModelFactories(ci2, bw.getStaticModels(), bw.getEnumModels(), bw.getModelCache()); - - bw.setExposureLevel(BeansWrapper.EXPOSE_ALL); - ClassIntrospector ci3 = bw.getClassIntrospector(); - assertNotSame(ci2, ci3); - checkRegisteredModelFactories(ci2); - checkRegisteredModelFactories(ci3, bw.getStaticModels(), bw.getEnumModels(), bw.getModelCache()); - - MethodAppearanceFineTuner maf = new MethodAppearanceFineTuner() { - @Override - public void process(MethodAppearanceDecisionInput in, MethodAppearanceDecision out) { - // nop - } - }; - bw.setMethodAppearanceFineTuner(maf); - ClassIntrospector ci4 = bw.getClassIntrospector(); - assertNotSame(ci3, ci4); - checkRegisteredModelFactories(ci3); - checkRegisteredModelFactories(ci4, bw.getStaticModels(), bw.getEnumModels(), bw.getModelCache()); - - bw.setExposeFields(true); - assertSame(ci4, bw.getClassIntrospector()); - bw.setExposureLevel(BeansWrapper.EXPOSE_ALL); - assertSame(ci4, bw.getClassIntrospector()); - bw.setMethodAppearanceFineTuner(maf); - assertSame(ci4, bw.getClassIntrospector()); - checkRegisteredModelFactories(ci4, bw.getStaticModels(), bw.getEnumModels(), bw.getModelCache()); - } - - private void checkRegisteredModelFactories(ClassIntrospector ci, Object... expected) { - Object[] actualRefs = ci.getRegisteredModelFactoriesSnapshot(); - - scanActuals: for (Object actaulRef : actualRefs) { - Object actualItem = ((Reference) actaulRef).get(); - for (Object expectedItem : expected) { - if (actualItem == expectedItem) { - continue scanActuals; - } - } - fail("Actaul item " + actualItem + " is not among the expected items"); - } - - scanExpecteds: for (Object expectedItem : expected) { - for (Object ref : actualRefs) { - Object actualItem = ((Reference) ref).get(); - if (actualItem == expectedItem) { - continue scanExpecteds; - } - } - fail("Expected item " + expectedItem + " is not among the actual items"); - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperDesc.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperDesc.java b/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperDesc.java deleted file mode 100644 index 6fd9a8c..0000000 --- a/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperDesc.java +++ /dev/null @@ -1,30 +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.freemarker.core.model.impl.beans; - -import org.apache.freemarker.core.Configuration; - -public class BeansWrapperDesc extends BeansWrapperWithShortedMethods { - - public BeansWrapperDesc() { - super(Configuration.VERSION_3_0_0, true); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperInc.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperInc.java b/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperInc.java deleted file mode 100644 index b347b95..0000000 --- a/src/test/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperInc.java +++ /dev/null @@ -1,30 +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.freemarker.core.model.impl.beans; - -import org.apache.freemarker.core.Configuration; - -public class BeansWrapperInc extends BeansWrapperWithShortedMethods { - - public BeansWrapperInc() { - super(Configuration.VERSION_3_0_0, false); - } - -}