http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/TypeFlagsTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/TypeFlagsTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/TypeFlagsTest.java new file mode 100644 index 0000000..fe11d1c --- /dev/null +++ b/freemarker-core-test/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.Builder(Configuration.VERSION_3_0_0).build(); + + 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/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/_OutputFormatTestAPI.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/_OutputFormatTestAPI.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/_OutputFormatTestAPI.java new file mode 100644 index 0000000..0a479aa --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/_OutputFormatTestAPI.java @@ -0,0 +1,35 @@ +/* + * 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.outputformat; + +public final class _OutputFormatTestAPI { + + private _OutputFormatTestAPI() { + // + } + + public static String getMarkupContent(CommonTemplateMarkupOutputModel<?> tm) { + return tm.getMarkupContent(); + } + + public static String getPlainTextContent(CommonTemplateMarkupOutputModel<?> tm) { + return tm.getPlainTextContent(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/impl/CombinedMarkupOutputFormatTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/impl/CombinedMarkupOutputFormatTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/impl/CombinedMarkupOutputFormatTest.java new file mode 100644 index 0000000..19e45de --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/impl/CombinedMarkupOutputFormatTest.java @@ -0,0 +1,194 @@ +/* + * 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.outputformat.impl; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.StringWriter; + +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.outputformat.MarkupOutputFormat; +import org.apache.freemarker.core.outputformat._OutputFormatTestAPI; +import org.junit.Test; + +public class CombinedMarkupOutputFormatTest { + + private static final CombinedMarkupOutputFormat HTML_RTF = new CombinedMarkupOutputFormat( + HTMLOutputFormat.INSTANCE, RTFOutputFormat.INSTANCE); + private static final CombinedMarkupOutputFormat XML_XML = new CombinedMarkupOutputFormat( + XMLOutputFormat.INSTANCE, XMLOutputFormat.INSTANCE); + + @Test + public void testName() { + assertEquals("HTML{RTF}", HTML_RTF.getName()); + assertEquals("XML{XML}", XML_XML.getName()); + } + + @Test + public void testOutputMO() throws TemplateModelException, IOException { + StringWriter out = new StringWriter(); + + HTML_RTF.output(HTML_RTF.fromMarkup("<pre>\\par Test "), out); + HTML_RTF.output(HTML_RTF.fromPlainTextByEscaping("foo { bar } \\ "), out); + HTML_RTF.output(HTML_RTF.fromPlainTextByEscaping("& baaz "), out); + HTML_RTF.output(HTML_RTF.fromPlainTextByEscaping("\\par & qwe"), out); + HTML_RTF.output(HTML_RTF.fromMarkup("\\par{0} End</pre>"), out); + + assertEquals( + "<pre>\\par Test " + + "foo \\{ bar \\} \\\\ " + + "& baaz " + + "\\\\par & qwe" + + "\\par{0} End</pre>", + out.toString()); + } + + @Test + public void testOutputMO2() throws TemplateModelException, IOException { + StringWriter out = new StringWriter(); + + XML_XML.output(XML_XML.fromMarkup("<pre><p> Test "), out); + XML_XML.output(XML_XML.fromPlainTextByEscaping("a & b < c"), out); + XML_XML.output(XML_XML.fromMarkup(" End</pre>"), out); + + assertEquals( + "<pre><p> Test " + + "a &amp; b &lt; c" + + " End</pre>", + out.toString()); + } + + @Test + public void testOutputMO3() throws TemplateModelException, IOException { + MarkupOutputFormat outputFormat = new CombinedMarkupOutputFormat( + RTFOutputFormat.INSTANCE, + new CombinedMarkupOutputFormat(RTFOutputFormat.INSTANCE, RTFOutputFormat.INSTANCE)); + StringWriter out = new StringWriter(); + + outputFormat.output(outputFormat.fromPlainTextByEscaping("b{}"), out); + outputFormat.output(outputFormat.fromMarkup("a{}"), out); + + assertEquals( + "b\\\\\\\\\\\\\\{\\\\\\\\\\\\\\}" + + "a{}", + out.toString()); + } + + @Test + public void testOutputString() throws TemplateModelException, IOException { + StringWriter out = new StringWriter(); + + HTML_RTF.output("a", out); + HTML_RTF.output("{", out); + HTML_RTF.output("<b>}c", out); + + assertEquals("a\\{<b>\\}c", out.toString()); + } + + @Test + public void testOutputString2() throws TemplateModelException, IOException { + StringWriter out = new StringWriter(); + + XML_XML.output("a", out); + XML_XML.output("&", out); + XML_XML.output("<b>", out); + + assertEquals("a&amp;&lt;b&gt;", out.toString()); + } + + @Test + public void testFromPlainTextByEscaping() throws TemplateModelException { + String plainText = "a\\b&c"; + TemplateCombinedMarkupOutputModel mo = HTML_RTF.fromPlainTextByEscaping(plainText); + assertSame(plainText, _OutputFormatTestAPI.getPlainTextContent(mo)); + assertNull(_OutputFormatTestAPI.getMarkupContent(mo)); // Not the MO's duty to calculate it! + } + + @Test + public void testFromMarkup() throws TemplateModelException { + String markup = "a \\par <b>"; + TemplateCombinedMarkupOutputModel mo = HTML_RTF.fromMarkup(markup); + assertSame(markup, _OutputFormatTestAPI.getMarkupContent(mo)); + assertNull(_OutputFormatTestAPI.getPlainTextContent(mo)); // Not the MO's duty to calculate it! + } + + @Test + public void testGetMarkup() throws TemplateModelException { + { + String markup = "a \\par <b>"; + TemplateCombinedMarkupOutputModel mo = HTML_RTF.fromMarkup(markup); + assertSame(markup, HTML_RTF.getMarkupString(mo)); + } + + { + String safe = "abc"; + TemplateCombinedMarkupOutputModel mo = HTML_RTF.fromPlainTextByEscaping(safe); + assertSame(safe, HTML_RTF.getMarkupString(mo)); + } + } + + @Test + public void testConcat() throws Exception { + assertMO( + "ab", null, + HTML_RTF.concat( + new TemplateCombinedMarkupOutputModel("a", null, HTML_RTF), + new TemplateCombinedMarkupOutputModel("b", null, HTML_RTF))); + assertMO( + null, "ab", + HTML_RTF.concat( + new TemplateCombinedMarkupOutputModel(null, "a", HTML_RTF), + new TemplateCombinedMarkupOutputModel(null, "b", HTML_RTF))); + assertMO( + null, "{<a>}\\{<b>\\}", + HTML_RTF.concat( + new TemplateCombinedMarkupOutputModel(null, "{<a>}", HTML_RTF), + new TemplateCombinedMarkupOutputModel("{<b>}", null, HTML_RTF))); + assertMO( + null, "\\{<a>\\}{<b>}", + HTML_RTF.concat( + new TemplateCombinedMarkupOutputModel("{<a>}", null, HTML_RTF), + new TemplateCombinedMarkupOutputModel(null, "{<b>}", HTML_RTF))); + } + + @Test + public void testEscaplePlainText() throws TemplateModelException { + assertEquals("", HTML_RTF.escapePlainText("")); + assertEquals("a", HTML_RTF.escapePlainText("a")); + assertEquals("\\{a\\\\b&\\}", HTML_RTF.escapePlainText("{a\\b&}")); + assertEquals("a\\\\b&", HTML_RTF.escapePlainText("a\\b&")); + assertEquals("\\{\\}&", HTML_RTF.escapePlainText("{}&")); + + assertEquals("a", XML_XML.escapePlainText("a")); + assertEquals("a&apos;b", XML_XML.escapePlainText("a'b")); + } + + private void assertMO(String pc, String mc, TemplateCombinedMarkupOutputModel mo) { + assertEquals(pc, _OutputFormatTestAPI.getPlainTextContent(mo)); + assertEquals(mc, _OutputFormatTestAPI.getMarkupContent(mo)); + } + + @Test + public void testGetMimeType() { + assertEquals("text/html", HTML_RTF.getMimeType()); + assertEquals("application/xml", XML_XML.getMimeType()); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/impl/HTMLOutputFormatTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/impl/HTMLOutputFormatTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/impl/HTMLOutputFormatTest.java new file mode 100644 index 0000000..2199179 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/impl/HTMLOutputFormatTest.java @@ -0,0 +1,187 @@ +/* + * 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.outputformat.impl; + +import static org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat.*; +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.StringWriter; + +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.outputformat.CommonMarkupOutputFormat; +import org.apache.freemarker.core.outputformat._OutputFormatTestAPI; +import org.junit.Test; + +/** + * This actually more a {@link CommonMarkupOutputFormat} test. + */ +public class HTMLOutputFormatTest { + + @Test + public void testOutputMO() throws TemplateModelException, IOException { + StringWriter out = new StringWriter(); + + INSTANCE.output(INSTANCE.fromMarkup("<p>Test "), out); + INSTANCE.output(INSTANCE.fromPlainTextByEscaping("foo & bar "), out); + INSTANCE.output(INSTANCE.fromPlainTextByEscaping("baaz "), out); + INSTANCE.output(INSTANCE.fromPlainTextByEscaping("<b>A</b> <b>B</b> <b>C</b>"), out); + INSTANCE.output(INSTANCE.fromPlainTextByEscaping(""), out); + INSTANCE.output(INSTANCE.fromPlainTextByEscaping("\"' x's \"y\" \""), out); + INSTANCE.output(INSTANCE.fromMarkup("</p>"), out); + + assertEquals( + "<p>Test " + + "foo & bar " + + "baaz " + + "<b>A</b> <b>B</b> <b>C</b>" + + ""' x's "y" "" + + "</p>", + out.toString()); + } + + @Test + public void testOutputString() throws TemplateModelException, IOException { + StringWriter out = new StringWriter(); + + INSTANCE.output("a", out); + INSTANCE.output("<", out); + INSTANCE.output("b'c", out); + + assertEquals("a<b'c", out.toString()); + } + + @Test + public void testFromPlainTextByEscaping() throws TemplateModelException { + String plainText = "a&b"; + TemplateHTMLOutputModel mo = INSTANCE.fromPlainTextByEscaping(plainText); + assertSame(plainText, _OutputFormatTestAPI.getPlainTextContent(mo)); + assertNull(_OutputFormatTestAPI.getMarkupContent(mo)); // Not the MO's duty to calculate it! + } + + @Test + public void testFromMarkup() throws TemplateModelException { + String markup = "a&b"; + TemplateHTMLOutputModel mo = INSTANCE.fromMarkup(markup); + assertSame(markup, _OutputFormatTestAPI.getMarkupContent(mo)); + assertNull(_OutputFormatTestAPI.getPlainTextContent(mo)); // Not the MO's duty to calculate it! + } + + @Test + public void testGetMarkup() throws TemplateModelException { + { + String markup = "a&b"; + TemplateHTMLOutputModel mo = INSTANCE.fromMarkup(markup); + assertSame(markup, INSTANCE.getMarkupString(mo)); + } + + { + String safe = "abc"; + TemplateHTMLOutputModel mo = INSTANCE.fromPlainTextByEscaping(safe); + assertSame(safe, INSTANCE.getMarkupString(mo)); + } + { + String safe = ""; + TemplateHTMLOutputModel mo = INSTANCE.fromPlainTextByEscaping(safe); + assertSame(safe, INSTANCE.getMarkupString(mo)); + } + { + TemplateHTMLOutputModel mo = INSTANCE.fromPlainTextByEscaping("<abc"); + assertEquals("<abc", INSTANCE.getMarkupString(mo)); + } + { + TemplateHTMLOutputModel mo = INSTANCE.fromPlainTextByEscaping("abc>"); + assertEquals("abc>", INSTANCE.getMarkupString(mo)); + } + { + TemplateHTMLOutputModel mo = INSTANCE.fromPlainTextByEscaping("<abc>"); + assertEquals("<abc>", INSTANCE.getMarkupString(mo)); + } + { + TemplateHTMLOutputModel mo = INSTANCE.fromPlainTextByEscaping("a&bc"); + assertEquals("a&bc", INSTANCE.getMarkupString(mo)); + } + { + TemplateHTMLOutputModel mo = INSTANCE.fromPlainTextByEscaping("a&b&c"); + assertEquals("a&b&c", INSTANCE.getMarkupString(mo)); + } + { + TemplateHTMLOutputModel mo = INSTANCE.fromPlainTextByEscaping("a<&>b&c"); + assertEquals("a<&>b&c", INSTANCE.getMarkupString(mo)); + } + { + TemplateHTMLOutputModel mo = INSTANCE.fromPlainTextByEscaping("\"<a<&>b&c>\""); + assertEquals(""<a<&>b&c>"", INSTANCE.getMarkupString(mo)); + } + { + TemplateHTMLOutputModel mo = INSTANCE.fromPlainTextByEscaping("<"); + assertEquals("<", INSTANCE.getMarkupString(mo)); + } + { + TemplateHTMLOutputModel mo = INSTANCE.fromPlainTextByEscaping("'"); + String mc = INSTANCE.getMarkupString(mo); + assertEquals("'", mc); + assertSame(mc, INSTANCE.getMarkupString(mo)); // cached + } + } + + @Test + public void testConcat() throws Exception { + assertMO( + "ab", null, + INSTANCE.concat(new TemplateHTMLOutputModel("a", null), new TemplateHTMLOutputModel("b", null))); + assertMO( + null, "ab", + INSTANCE.concat(new TemplateHTMLOutputModel(null, "a"), new TemplateHTMLOutputModel(null, "b"))); + assertMO( + null, "<a><b>", + INSTANCE.concat(new TemplateHTMLOutputModel(null, "<a>"), new TemplateHTMLOutputModel("<b>", null))); + assertMO( + null, "<a><b>", + INSTANCE.concat(new TemplateHTMLOutputModel("<a>", null), new TemplateHTMLOutputModel(null, "<b>"))); + } + + @Test + public void testEscaplePlainText() { + assertEquals("", INSTANCE.escapePlainText("")); + assertEquals("a", INSTANCE.escapePlainText("a")); + assertEquals("<a&b'c"d>", INSTANCE.escapePlainText("<a&b'c\"d>")); + assertEquals("a&b", INSTANCE.escapePlainText("a&b")); + assertEquals("<>", INSTANCE.escapePlainText("<>")); + } + + @Test + public void testIsEmpty() throws Exception { + assertTrue(INSTANCE.isEmpty(INSTANCE.fromMarkup(""))); + assertTrue(INSTANCE.isEmpty(INSTANCE.fromPlainTextByEscaping(""))); + assertFalse(INSTANCE.isEmpty(INSTANCE.fromMarkup(" "))); + assertFalse(INSTANCE.isEmpty(INSTANCE.fromPlainTextByEscaping(" "))); + } + + private void assertMO(String pc, String mc, TemplateHTMLOutputModel mo) { + assertEquals(pc, _OutputFormatTestAPI.getPlainTextContent(mo)); + assertEquals(mc, _OutputFormatTestAPI.getMarkupContent(mo)); + } + + @Test + public void testGetMimeType() { + assertEquals("text/html", INSTANCE.getMimeType()); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/impl/RTFOutputFormatTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/impl/RTFOutputFormatTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/impl/RTFOutputFormatTest.java new file mode 100644 index 0000000..13563f5 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/outputformat/impl/RTFOutputFormatTest.java @@ -0,0 +1,129 @@ +/* + * 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.outputformat.impl; + +import static org.apache.freemarker.core.outputformat.impl.RTFOutputFormat.*; +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.StringWriter; + +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.outputformat._OutputFormatTestAPI; +import org.junit.Test; + +public class RTFOutputFormatTest { + + @Test + public void testOutputMO() throws TemplateModelException, IOException { + StringWriter out = new StringWriter(); + + INSTANCE.output(INSTANCE.fromMarkup("\\par Test "), out); + INSTANCE.output(INSTANCE.fromPlainTextByEscaping("foo { bar } \\ "), out); + INSTANCE.output(INSTANCE.fromPlainTextByEscaping("baaz "), out); + INSTANCE.output(INSTANCE.fromPlainTextByEscaping("\\par qweqwe"), out); + INSTANCE.output(INSTANCE.fromMarkup("\\par{0} End"), out); + + assertEquals( + "\\par Test " + + "foo \\{ bar \\} \\\\ " + + "baaz " + + "\\\\par qweqwe" + + "\\par{0} End", + out.toString()); + } + + @Test + public void testOutputString() throws TemplateModelException, IOException { + StringWriter out = new StringWriter(); + + INSTANCE.output("a", out); + INSTANCE.output("{", out); + INSTANCE.output("b}c", out); + + assertEquals("a\\{b\\}c", out.toString()); + } + + @Test + public void testFromPlainTextByEscaping() throws TemplateModelException { + String plainText = "a\\b"; + TemplateRTFOutputModel mo = INSTANCE.fromPlainTextByEscaping(plainText); + assertSame(plainText, _OutputFormatTestAPI.getPlainTextContent(mo)); + assertNull(_OutputFormatTestAPI.getMarkupContent(mo)); // Not the MO's duty to calculate it! + } + + @Test + public void testFromMarkup() throws TemplateModelException { + String markup = "a \\par b"; + TemplateRTFOutputModel mo = INSTANCE.fromMarkup(markup); + assertSame(markup, _OutputFormatTestAPI.getMarkupContent(mo)); + assertNull(_OutputFormatTestAPI.getPlainTextContent(mo)); // Not the MO's duty to calculate it! + } + + @Test + public void testGetMarkup() throws TemplateModelException { + { + String markup = "a \\par b"; + TemplateRTFOutputModel mo = INSTANCE.fromMarkup(markup); + assertSame(markup, INSTANCE.getMarkupString(mo)); + } + + { + String safe = "abc"; + TemplateRTFOutputModel mo = INSTANCE.fromPlainTextByEscaping(safe); + assertSame(safe, INSTANCE.getMarkupString(mo)); + } + } + + @Test + public void testConcat() throws Exception { + assertMO( + "ab", null, + INSTANCE.concat(new TemplateRTFOutputModel("a", null), new TemplateRTFOutputModel("b", null))); + assertMO( + null, "ab", + INSTANCE.concat(new TemplateRTFOutputModel(null, "a"), new TemplateRTFOutputModel(null, "b"))); + assertMO( + null, "{a}\\{b\\}", + INSTANCE.concat(new TemplateRTFOutputModel(null, "{a}"), new TemplateRTFOutputModel("{b}", null))); + assertMO( + null, "\\{a\\}{b}", + INSTANCE.concat(new TemplateRTFOutputModel("{a}", null), new TemplateRTFOutputModel(null, "{b}"))); + } + + @Test + public void testEscaplePlainText() { + assertEquals("", INSTANCE.escapePlainText("")); + assertEquals("a", INSTANCE.escapePlainText("a")); + assertEquals("\\{a\\\\b\\}", INSTANCE.escapePlainText("{a\\b}")); + assertEquals("a\\\\b", INSTANCE.escapePlainText("a\\b")); + assertEquals("\\{\\}", INSTANCE.escapePlainText("{}")); + } + + private void assertMO(String pc, String mc, TemplateRTFOutputModel mo) { + assertEquals(pc, _OutputFormatTestAPI.getPlainTextContent(mo)); + assertEquals(mc, _OutputFormatTestAPI.getMarkupContent(mo)); + } + + @Test + public void testGetMimeType() { + assertEquals("application/rtf", INSTANCE.getMimeType()); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/DefaultTemplateResolverTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/DefaultTemplateResolverTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/DefaultTemplateResolverTest.java new file mode 100644 index 0000000..a7063fd --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/DefaultTemplateResolverTest.java @@ -0,0 +1,365 @@ +/* + * 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.templateresolver; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.util.Locale; + +import org.apache.freemarker.core.Configuration; +import org.apache.freemarker.core.Template; +import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateLookupStrategy; +import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateNameFormat; +import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateResolver; +import org.apache.freemarker.core.templateresolver.impl.StringTemplateLoader; +import org.apache.freemarker.core.templateresolver.impl.StrongCacheStorage; +import org.apache.freemarker.test.MonitoredTemplateLoader; +import org.apache.freemarker.test.MonitoredTemplateLoader.CloseSessionEvent; +import org.apache.freemarker.test.MonitoredTemplateLoader.CreateSessionEvent; +import org.apache.freemarker.test.MonitoredTemplateLoader.LoadEvent; +import org.apache.freemarker.test.TestConfigurationBuilder; +import org.hamcrest.Matchers; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; + +public class DefaultTemplateResolverTest { + + @Test + public void testCachedException() throws Exception { + MockTemplateLoader loader = new MockTemplateLoader(); + DefaultTemplateResolver tr = new DefaultTemplateResolver( + loader, + new StrongCacheStorage(), 1000L, + DefaultTemplateLookupStrategy.INSTANCE, true, + DefaultTemplateNameFormat.INSTANCE, + null, + new TestConfigurationBuilder().build()); + loader.setThrowException(true); + try { + tr.getTemplate("t", Locale.getDefault(), null).getTemplate(); + fail(); + } catch (IOException e) { + assertEquals("mock IO exception", e.getMessage()); + assertEquals(1, loader.getLoadAttemptCount()); + try { + tr.getTemplate("t", Locale.getDefault(), null).getTemplate(); + fail(); + } catch (IOException e2) { + // Still 1 - returned cached exception + assertThat(e2.getMessage(), + Matchers.allOf(Matchers.containsString("There was an error loading the template on an " + + "earlier attempt"))); + assertSame(e, e2.getCause()); + assertEquals(1, loader.getLoadAttemptCount()); + try { + Thread.sleep(1100L); + tr.getTemplate("t", Locale.getDefault(), null).getTemplate(); + fail(); + } catch (IOException e3) { + // Cache had to retest + assertEquals("mock IO exception", e.getMessage()); + assertEquals(2, loader.getLoadAttemptCount()); + } + } + } + } + + @Test + public void testCachedNotFound() throws Exception { + MockTemplateLoader loader = new MockTemplateLoader(); + DefaultTemplateResolver cache = new DefaultTemplateResolver( + loader, + new StrongCacheStorage(), 1000L, + DefaultTemplateLookupStrategy.INSTANCE, false, + DefaultTemplateNameFormat.INSTANCE, + null, new TestConfigurationBuilder().build()); + assertNull(cache.getTemplate("t", Locale.getDefault(), null).getTemplate()); + assertEquals(1, loader.getLoadAttemptCount()); + assertNull(cache.getTemplate("t", Locale.getDefault(), null).getTemplate()); + // Still 1 - returned cached exception + assertEquals(1, loader.getLoadAttemptCount()); + Thread.sleep(1100L); + assertNull(cache.getTemplate("t", Locale.getDefault(), null).getTemplate()); + // Cache had to retest + assertEquals(2, loader.getLoadAttemptCount()); + } + + private static class MockTemplateLoader implements TemplateLoader { + private boolean throwException; + private int loadAttemptCount; + + public void setThrowException(boolean throwException) { + this.throwException = throwException; + } + + public int getLoadAttemptCount() { + return loadAttemptCount; + } + + @Override + public TemplateLoaderSession createSession() { + return null; + } + + @Override + public TemplateLoadingResult load(String name, TemplateLoadingSource ifSourceDiffersFrom, + Serializable ifVersionDiffersFrom, TemplateLoaderSession session) throws IOException { + ++loadAttemptCount; + if (throwException) { + throw new IOException("mock IO exception"); + } + return TemplateLoadingResult.NOT_FOUND; + } + + @Override + public void resetState() { + // + } + + } + + @Test + public void testManualRemovalPlain() throws Exception { + StringTemplateLoader loader = new StringTemplateLoader(); + Configuration cfg = new TestConfigurationBuilder() + .cacheStorage(new StrongCacheStorage()) + .templateLoader(loader) + .templateUpdateDelayMilliseconds(Long.MAX_VALUE) + .build(); + + loader.putTemplate("1.ftl", "1 v1"); + loader.putTemplate("2.ftl", "2 v1"); + assertEquals("1 v1", cfg.getTemplate("1.ftl").toString()); + assertEquals("2 v1", cfg.getTemplate("2.ftl").toString()); + + loader.putTemplate("1.ftl", "1 v2"); + loader.putTemplate("2.ftl", "2 v2"); + assertEquals("1 v1", cfg.getTemplate("1.ftl").toString()); // no change + assertEquals("2 v1", cfg.getTemplate("2.ftl").toString()); // no change + + cfg.removeTemplateFromCache("1.ftl", cfg.getLocale(), null); + assertEquals("1 v2", cfg.getTemplate("1.ftl").toString()); // changed + assertEquals("2 v1", cfg.getTemplate("2.ftl").toString()); + + cfg.removeTemplateFromCache("2.ftl", cfg.getLocale(), null); + assertEquals("1 v2", cfg.getTemplate("1.ftl").toString()); + assertEquals("2 v2", cfg.getTemplate("2.ftl").toString()); // changed + } + + @Test + public void testManualRemovalI18ed() throws Exception { + StringTemplateLoader loader = new StringTemplateLoader(); + Configuration cfg = new TestConfigurationBuilder() + .cacheStorage(new StrongCacheStorage()) + .templateLoader(loader) + .templateUpdateDelayMilliseconds(Long.MAX_VALUE) + .build(); + + loader.putTemplate("1_en_US.ftl", "1_en_US v1"); + loader.putTemplate("1_en.ftl", "1_en v1"); + loader.putTemplate("1.ftl", "1 v1"); + + assertEquals("1_en_US v1", cfg.getTemplate("1.ftl").toString()); + assertEquals("1_en v1", cfg.getTemplate("1.ftl", Locale.UK).toString()); + assertEquals("1 v1", cfg.getTemplate("1.ftl", Locale.GERMANY).toString()); + + loader.putTemplate("1_en_US.ftl", "1_en_US v2"); + loader.putTemplate("1_en.ftl", "1_en v2"); + loader.putTemplate("1.ftl", "1 v2"); + assertEquals("1_en_US v1", cfg.getTemplate("1.ftl").toString()); + assertEquals("1_en v1", cfg.getTemplate("1.ftl", Locale.UK).toString()); + assertEquals("1 v1", cfg.getTemplate("1.ftl", Locale.GERMANY).toString()); + + cfg.removeTemplateFromCache("1.ftl", cfg.getLocale(), null); + assertEquals("1_en_US v2", cfg.getTemplate("1.ftl").toString()); + assertEquals("1_en v1", cfg.getTemplate("1.ftl", Locale.UK).toString()); + assertEquals("1 v1", cfg.getTemplate("1.ftl", Locale.GERMANY).toString()); + assertEquals("1 v2", cfg.getTemplate("1.ftl", Locale.ITALY).toString()); + + cfg.removeTemplateFromCache("1.ftl", Locale.GERMANY, null); + assertEquals("1_en v1", cfg.getTemplate("1.ftl", Locale.UK).toString()); + assertEquals("1 v2", cfg.getTemplate("1.ftl", Locale.GERMANY).toString()); + + cfg.removeTemplateFromCache("1.ftl", Locale.CANADA, null); + assertEquals("1_en v1", cfg.getTemplate("1.ftl", Locale.UK).toString()); + + cfg.removeTemplateFromCache("1.ftl", Locale.UK, null); + assertEquals("1_en v2", cfg.getTemplate("1.ftl", Locale.UK).toString()); + } + + @Test + public void testZeroUpdateDelay() throws Exception { + MonitoredTemplateLoader loader = new MonitoredTemplateLoader(); + TestConfigurationBuilder cfgB = new TestConfigurationBuilder() + .cacheStorage(new StrongCacheStorage()) + .templateLoader(loader) + .templateUpdateDelayMilliseconds(0); + + Configuration cfg = cfgB.build(); + + for (int i = 1; i <= 3; i++) { + loader.putTextTemplate("t.ftl", "v" + i); + assertEquals("v" + i, cfg.getTemplate("t.ftl").toString()); + } + + loader.clearEvents(); + loader.putTextTemplate("t.ftl", "v8"); + assertEquals("v8", cfg.getTemplate("t.ftl").toString()); + assertEquals("v8", cfg.getTemplate("t.ftl").toString()); + loader.putTextTemplate("t.ftl", "v9"); + assertEquals("v9", cfg.getTemplate("t.ftl").toString()); + assertEquals("v9", cfg.getTemplate("t.ftl").toString()); + assertEquals( + ImmutableList.of( + new LoadEvent("t_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND), // v8 + new LoadEvent("t_en.ftl", TemplateLoadingResultStatus.NOT_FOUND), + new LoadEvent("t.ftl", TemplateLoadingResultStatus.OPENED), + + new LoadEvent("t_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND), // v8 + new LoadEvent("t_en.ftl", TemplateLoadingResultStatus.NOT_FOUND), + new LoadEvent("t.ftl", TemplateLoadingResultStatus.NOT_MODIFIED), + + new LoadEvent("t_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND), // v9 + new LoadEvent("t_en.ftl", TemplateLoadingResultStatus.NOT_FOUND), + new LoadEvent("t.ftl", TemplateLoadingResultStatus.OPENED), + + new LoadEvent("t_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND), // v9 + new LoadEvent("t_en.ftl", TemplateLoadingResultStatus.NOT_FOUND), + new LoadEvent("t.ftl", TemplateLoadingResultStatus.NOT_MODIFIED) + ), + loader.getEvents(LoadEvent.class)); + + cfg = cfgB.localizedLookup(false).build(); + loader.clearEvents(); + loader.putTextTemplate("t.ftl", "v10"); + assertEquals("v10", cfg.getTemplate("t.ftl").toString()); + loader.putTextTemplate("t.ftl", "v11"); // same time stamp, different content + assertEquals("v11", cfg.getTemplate("t.ftl").toString()); + assertEquals("v11", cfg.getTemplate("t.ftl").toString()); + assertEquals("v11", cfg.getTemplate("t.ftl").toString()); + Thread.sleep(17L); + assertEquals("v11", cfg.getTemplate("t.ftl").toString()); + loader.putTextTemplate("t.ftl", "v12"); + assertEquals("v12", cfg.getTemplate("t.ftl").toString()); + assertEquals("v12", cfg.getTemplate("t.ftl").toString()); + assertEquals( + ImmutableList.of( + new LoadEvent("t.ftl", TemplateLoadingResultStatus.OPENED), // v10 + new LoadEvent("t.ftl", TemplateLoadingResultStatus.OPENED), // v11 + new LoadEvent("t.ftl", TemplateLoadingResultStatus.NOT_MODIFIED), + new LoadEvent("t.ftl", TemplateLoadingResultStatus.NOT_MODIFIED), + new LoadEvent("t.ftl", TemplateLoadingResultStatus.NOT_MODIFIED), + new LoadEvent("t.ftl", TemplateLoadingResultStatus.OPENED), // v12 + new LoadEvent("t.ftl", TemplateLoadingResultStatus.NOT_MODIFIED) + ), + loader.getEvents(LoadEvent.class)); + } + + @Test + public void testWrongEncodingReload() throws Exception { + MonitoredTemplateLoader loader = new MonitoredTemplateLoader(); + loader.putBinaryTemplate("utf-8_en.ftl", "<#ftl encoding='utf-8'>Béka"); + loader.putBinaryTemplate("utf-8.ftl", "Bar"); + loader.putBinaryTemplate("iso-8859-1_en_US.ftl", "<#ftl encoding='ISO-8859-1'>Béka", + StandardCharsets.ISO_8859_1, "v1"); + Configuration cfg = new TestConfigurationBuilder().templateLoader(loader).build(); + + { + Template t = cfg.getTemplate("utf-8.ftl"); + assertEquals("utf-8.ftl", t.getLookupName()); + assertEquals("utf-8_en.ftl", t.getSourceName()); + assertEquals(StandardCharsets.UTF_8, t.getActualSourceEncoding()); + assertEquals("Béka", t.toString()); + + assertEquals( + ImmutableList.of( + CreateSessionEvent.INSTANCE, + new LoadEvent("utf-8_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND), + new LoadEvent("utf-8_en.ftl", TemplateLoadingResultStatus.OPENED), + CloseSessionEvent.INSTANCE), + loader.getEvents()); + } + + { + loader.clearEvents(); + + Template t = cfg.getTemplate("iso-8859-1.ftl"); + assertEquals("iso-8859-1.ftl", t.getLookupName()); + assertEquals("iso-8859-1_en_US.ftl", t.getSourceName()); + assertEquals(StandardCharsets.ISO_8859_1, t.getActualSourceEncoding()); + assertEquals("Béka", t.toString()); + + assertEquals( + ImmutableList.of( + CreateSessionEvent.INSTANCE, + new LoadEvent("iso-8859-1_en_US.ftl", TemplateLoadingResultStatus.OPENED), + CloseSessionEvent.INSTANCE), + loader.getEvents()); + } + } + + @Test + public void testNoWrongEncodingForTemplateLoader2WithReader() throws Exception { + MonitoredTemplateLoader loader = new MonitoredTemplateLoader(); + loader.putTextTemplate("foo_en.ftl", "<#ftl encoding='utf-8'>Å"); + loader.putTextTemplate("foo.ftl", "B"); + Configuration cfg = new TestConfigurationBuilder().templateLoader(loader).build(); + + { + Template t = cfg.getTemplate("foo.ftl"); + assertEquals("foo.ftl", t.getLookupName()); + assertEquals("foo_en.ftl", t.getSourceName()); + assertNull(t.getActualSourceEncoding()); + assertEquals("Å", t.toString()); + + assertEquals( + ImmutableList.of( + CreateSessionEvent.INSTANCE, + new LoadEvent("foo_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND), + new LoadEvent("foo_en.ftl", TemplateLoadingResultStatus.OPENED), + CloseSessionEvent.INSTANCE), + loader.getEvents()); + } + } + + @Test + public void testTemplateNameFormatException() throws Exception { + Configuration cfg = new TestConfigurationBuilder() + .templateNameFormat(DefaultTemplateNameFormat.INSTANCE) + .build(); + try { + cfg.getTemplate("../x"); + fail(); + } catch (MalformedTemplateNameException e) { + // expected + } + try { + cfg.getTemplate("\\x"); + fail(); + } catch (MalformedTemplateNameException e) { + // expected + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/FileTemplateLoaderTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/FileTemplateLoaderTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/FileTemplateLoaderTest.java new file mode 100644 index 0000000..393dbae --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/FileTemplateLoaderTest.java @@ -0,0 +1,122 @@ +/* + * 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.templateresolver; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.SystemUtils; +import org.apache.freemarker.core.Configuration; +import org.apache.freemarker.core.TemplateNotFoundException; +import org.apache.freemarker.core.templateresolver.impl.FileTemplateLoader; +import org.apache.freemarker.test.TestConfigurationBuilder; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.io.Files; + +public class FileTemplateLoaderTest { + + private File templateRootDir; + + private Configuration cfg; + + @Before + public void setup() throws IOException { + templateRootDir = Files.createTempDir(); + File sub1Dir = new File(templateRootDir, "sub1"); + File sub2Dir = new File(sub1Dir, "sub2"); + if (!sub2Dir.mkdirs()) { + throw new IOException("Failed to invoke subdirectories"); + } + File tFile = new File(sub2Dir, "t.ftl"); + FileUtils.write(tFile, "foo"); + + cfg = new TestConfigurationBuilder().templateLoader(new FileTemplateLoader(templateRootDir)).build(); + } + + @Test + public void testSuccessful() throws Exception { + for (int i = 0; i < 2; i++) { + assertEquals("foo", cfg.getTemplate("sub1/sub2/t.ftl").toString()); + } + } + + @Test + public void testSuccessful2() throws Exception { + ((FileTemplateLoader) cfg.getTemplateLoader()).setEmulateCaseSensitiveFileSystem(true); + for (int i = 0; i < 2; i++) { + cfg.clearTemplateCache(); + assertEquals("foo", cfg.getTemplate("sub1/sub2/t.ftl").toString()); + } + } + + + @Test + public void testNotFound() throws Exception { + for (int i = 0; i < 2; i++) { + try { + cfg.getTemplate("sub1X/sub2/t.ftl"); + fail(); + } catch (TemplateNotFoundException e) { + assertThat(e.getMessage(), containsString("sub1X")); + assertNull(e.getCause()); + } + } + } + + @Test + public void testCaseSensitivity() throws Exception { + for (boolean emuCaseSensFS : new boolean[] { false, true }) { + for (String nameWithBadCase : new String[] { "SUB1/sub2/t.ftl", "sub1/SUB2/t.ftl", "sub1/sub2/T.FTL" }) { + ((FileTemplateLoader) cfg.getTemplateLoader()).setEmulateCaseSensitiveFileSystem(emuCaseSensFS); + cfg.clearTemplateCache(); + + if ((SystemUtils.IS_OS_WINDOWS || SystemUtils.IS_OS_MAC_OSX) && !emuCaseSensFS) { + assertEquals("foo", cfg.getTemplate(nameWithBadCase).toString()); + } else { + assertEquals("foo", cfg.getTemplate(nameWithBadCase.toLowerCase()).toString()); + try { + cfg.getTemplate(nameWithBadCase); + fail(); + } catch (TemplateNotFoundException e) { + assertThat(e.getMessage(), containsString(nameWithBadCase)); + assertNull(e.getCause()); + } + } + } + } + } + + @Test + public void testDefault() throws IOException { + assertFalse(new FileTemplateLoader(templateRootDir).getEmulateCaseSensitiveFileSystem()); + } + + @After + public void tearDown() throws IOException { + FileUtils.deleteDirectory(templateRootDir); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/MultiTemplateLoaderTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/MultiTemplateLoaderTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/MultiTemplateLoaderTest.java new file mode 100644 index 0000000..c8531c5 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/MultiTemplateLoaderTest.java @@ -0,0 +1,99 @@ +/* + * 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.templateresolver; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +import org.apache.commons.io.IOUtils; +import org.apache.freemarker.core.templateresolver.impl.ByteArrayTemplateLoader; +import org.apache.freemarker.core.templateresolver.impl.MultiTemplateLoader; +import org.apache.freemarker.core.templateresolver.impl.StringTemplateLoader; +import org.junit.Test; + +public class MultiTemplateLoaderTest { + + @Test + public void testBasics() throws IOException { + StringTemplateLoader stl1 = new StringTemplateLoader(); + stl1.putTemplate("1.ftl", "1"); + stl1.putTemplate("both.ftl", "both 1"); + + StringTemplateLoader stl2 = new StringTemplateLoader(); + stl2.putTemplate("2.ftl", "2"); + stl2.putTemplate("both.ftl", "both 2"); + + MultiTemplateLoader mtl = new MultiTemplateLoader(stl1, stl2); + assertEquals("1", getTemplateContent(mtl, "1.ftl")); + assertEquals("2", getTemplateContent(mtl, "2.ftl")); + assertEquals("both 1", getTemplateContent(mtl, "both.ftl")); + assertNull(getTemplateContent(mtl, "neither.ftl")); + } + + @Test + public void testSticky() throws IOException { + testStickiness(true); + } + + @Test + public void testNonSticky() throws IOException { + testStickiness(false); + } + + private void testStickiness(boolean sticky) throws IOException { + StringTemplateLoader stl1 = new StringTemplateLoader(); + stl1.putTemplate("both.ftl", "both 1"); + + ByteArrayTemplateLoader stl2 = new ByteArrayTemplateLoader(); + stl2.putTemplate("both.ftl", "both 2".getBytes(StandardCharsets.UTF_8)); + + MultiTemplateLoader mtl = new MultiTemplateLoader(stl1, stl2); + mtl.setSticky(sticky); + + assertEquals("both 1", getTemplateContent(mtl, "both.ftl")); + assertTrue(stl1.removeTemplate("both.ftl")); + assertEquals("both 2", getTemplateContent(mtl, "both.ftl")); + stl1.putTemplate("both.ftl", "both 1"); + assertEquals(sticky ? "both 2" : "both 1", getTemplateContent(mtl, "both.ftl")); + assertTrue(stl2.removeTemplate("both.ftl")); + assertEquals("both 1", getTemplateContent(mtl, "both.ftl")); + } + + private String getTemplateContent(TemplateLoader tl, String name) throws IOException { + TemplateLoaderSession ses = tl.createSession(); + try { + TemplateLoadingResult res = tl.load(name, null, null, ses); + if (res.getStatus() == TemplateLoadingResultStatus.NOT_FOUND) { + return null; + } + return IOUtils.toString( + res.getReader() != null + ? res.getReader() + : new InputStreamReader(res.getInputStream(), StandardCharsets.UTF_8)); + } finally { + if (ses != null) { + ses.close(); + } + } + } + +}
