1   package org.apache.velocity.test;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.    
20   */
21  
22  import java.math.BigDecimal;
23  import java.math.BigInteger;
24  
25  import junit.framework.Test;
26  import junit.framework.TestCase;
27  import junit.framework.TestSuite;
28  
29  import org.apache.velocity.runtime.parser.node.MathUtils;
30  
31  /**
32   * Test arithmetic operations. Introduced after extending from Integer-only
33   * to Number-handling.
34   *
35   * @author <a href="mailto:pero@antaramusic.de">Peter Romianowski</a>
36   */
37  public class ArithmeticTestCase extends TestCase
38  {
39  
40      public ArithmeticTestCase(String testName)
41      {
42          super(testName);
43      }
44  
45      public static Test suite()
46      {
47         return new TestSuite(ArithmeticTestCase.class);
48      }
49  
50      public void testAdd()
51      {
52          addHelper (new Integer(10), new Short( (short)20), 30, Integer.class);
53          addHelper (new Byte((byte)10), new Short( (short)20), 30, Short.class);
54          addHelper (new Float(10), new Short( (short)20), 30, Float.class);
55          addHelper (new Byte((byte)10), new Double( 20), 30, Double.class);
56          addHelper (BigInteger.valueOf(10), new Integer( 20), 30, BigInteger.class);
57          addHelper (new Integer( 20), BigDecimal.valueOf(10),  30, BigDecimal.class);
58  
59          // Test overflow
60          addHelper (new Integer(Integer.MAX_VALUE), new Short( (short)20), (double)Integer.MAX_VALUE+20, Long.class);
61          addHelper (new Integer (20), new Long(Long.MAX_VALUE), (double)Long.MAX_VALUE+20, BigInteger.class);
62          addHelper (new Integer (-20), new Long(Long.MIN_VALUE), (double)Long.MIN_VALUE-20, BigInteger.class);
63      }
64  
65      private void addHelper (Number n1, Number n2, double expectedResult, Class expectedResultType)
66      {
67          Number result = MathUtils.add( n1, n2);
68          assertEquals ("The arithmetic operation produced an unexpected result.", expectedResult, result.doubleValue(), 0.01);
69          assertEquals ("ResultType does not match.", expectedResultType, result.getClass());
70      }
71  
72      public void testSubtract()
73      {
74          subtractHelper (new Integer(100), new Short( (short)20), 80, Integer.class);
75          subtractHelper (new Byte((byte)100), new Short( (short)20), 80, Short.class);
76          subtractHelper (new Float(100), new Short( (short)20), 80, Float.class);
77          subtractHelper (new Byte((byte)100), new Double( 20), 80, Double.class);
78          subtractHelper (BigInteger.valueOf(100), new Integer( 20), 80, BigInteger.class);
79          subtractHelper (new Integer( 100), BigDecimal.valueOf(20),  80, BigDecimal.class);
80  
81          // Test overflow
82          subtractHelper (new Integer(Integer.MIN_VALUE), new Short( (short)20), (double)Integer.MIN_VALUE-20, Long.class);
83          subtractHelper (new Integer (-20), new Long(Long.MAX_VALUE), -20d-(double)Long.MAX_VALUE, BigInteger.class);
84          subtractHelper (new Integer (Integer.MAX_VALUE), new Long(Long.MIN_VALUE), (double)Long.MAX_VALUE+(double)Integer.MAX_VALUE, BigInteger.class);
85      }
86  
87      private void subtractHelper (Number n1, Number n2, double expectedResult, Class expectedResultType)
88      {
89          Number result = MathUtils.subtract( n1, n2);
90          assertEquals ("The arithmetic operation produced an unexpected result.", expectedResult, result.doubleValue(), 0.01);
91          assertEquals ("ResultType does not match.", expectedResultType, result.getClass());
92      }
93  
94      public void testMultiply()
95      {
96          multiplyHelper (new Integer(10), new Short( (short)20), 200, Integer.class);
97          multiplyHelper (new Byte((byte)100), new Short( (short)20), 2000, Short.class);
98          multiplyHelper (new Byte((byte)100), new Short( (short)2000), 200000, Integer.class);
99          multiplyHelper (new Float(100), new Short( (short)20), 2000, Float.class);
100         multiplyHelper (new Byte((byte)100), new Double( 20), 2000, Double.class);
101         multiplyHelper (BigInteger.valueOf(100), new Integer( 20), 2000, BigInteger.class);
102         multiplyHelper (new Integer( 100), BigDecimal.valueOf(20),  2000, BigDecimal.class);
103 
104         // Test overflow
105         multiplyHelper (new Integer(Integer.MAX_VALUE), new Short( (short)10), (double)Integer.MAX_VALUE*10d, Long.class);
106         multiplyHelper (new Integer(Integer.MAX_VALUE), new Short( (short)-10), (double)Integer.MAX_VALUE*-10d, Long.class);
107         multiplyHelper (new Integer (20), new Long(Long.MAX_VALUE), 20d*(double)Long.MAX_VALUE, BigInteger.class);
108     }
109 
110     private void multiplyHelper (Number n1, Number n2, double expectedResult, Class expectedResultType)
111     {
112         Number result = MathUtils.multiply( n1, n2);
113         assertEquals ("The arithmetic operation produced an unexpected result.", expectedResult, result.doubleValue(), 0.01);
114         assertEquals ("ResultType does not match.", expectedResultType, result.getClass());
115     }
116 
117     public void testDivide()
118     {
119         divideHelper (new Integer(10), new Short( (short)2), 5, Integer.class);
120         divideHelper (new Byte((byte)10), new Short( (short)2), 5, Short.class);
121         divideHelper (BigInteger.valueOf(10), new Short( (short)2), 5, BigInteger.class);
122         divideHelper (new Integer(10), new Short( (short)4), 2, Integer.class);
123         divideHelper (new Integer(10), new Float( 2.5f), 4, Float.class);
124         divideHelper (new Integer(10), new Double( 2.5), 4, Double.class);
125         divideHelper (new Integer(10), new BigDecimal( 2.5), 4, BigDecimal.class);
126     }
127 
128     private void divideHelper (Number n1, Number n2, double expectedResult, Class expectedResultType)
129     {
130         Number result = MathUtils.divide( n1, n2);
131         assertEquals ("The arithmetic operation produced an unexpected result.", expectedResult, result.doubleValue(), 0.01);
132         assertEquals ("ResultType does not match.", expectedResultType, result.getClass());
133     }
134 
135     public void testModulo()
136     {
137         moduloHelper (new Integer(10), new Short( (short)2), 0, Integer.class);
138         moduloHelper (new Byte((byte)10), new Short( (short)3), 1, Short.class);
139         moduloHelper (BigInteger.valueOf(10), new Short( (short)4), 2, BigInteger.class);
140         moduloHelper (new Integer(10), new Float( 5.5f), 4.5, Float.class);
141 
142         try
143         {
144             moduloHelper (new Integer(10), new BigDecimal( 2.5), 4, BigDecimal.class);
145             fail ("Modulo with BigDecimal is not allowed! Should have thrown an ArithmeticException.");
146         }
147         catch( ArithmeticException e)
148         {
149             // do nothing
150         }
151     }
152 
153     private void moduloHelper (Number n1, Number n2, double expectedResult, Class expectedResultType)
154     {
155         Number result = MathUtils.modulo( n1, n2);
156         assertEquals ("The arithmetic operation produced an unexpected result.", expectedResult, result.doubleValue(), 0.01);
157         assertEquals ("ResultType does not match.", expectedResultType, result.getClass());
158     }
159 
160     public void testCompare()
161     {
162         compareHelper (new Integer(10), new Short( (short)10), 0);
163         compareHelper (new Integer(10), new Short( (short)11), -1);
164         compareHelper (BigInteger.valueOf(10), new Short( (short)11), -1);
165         compareHelper (new Byte((byte)10), new Short( (short)3), 1);
166         compareHelper (new Float(10), new Short( (short)11), -1);
167         compareHelper (new Double(10), new Short( (short)11), -1);
168     }
169 
170     private void compareHelper (Number n1, Number n2, int expectedResult)
171     {
172         int result = MathUtils.compare( n1, n2 );
173         assertEquals ("The arithmetic operation produced an unexpected result.", expectedResult, result);
174     }
175 
176 /*
177  *
178  *    COMMENT OUT FOR PERFORMANCE-MEASSUREMENTS
179  *
180  *    public void testProfile()
181  *    {
182  *
183  *        long start = System.currentTimeMillis();
184  *
185  *        Number v1 = new Long (1000);
186  *        Number v2 = new Double (10.23);
187  *        Number result = null;
188  *        for (int a = 0; a < 10000; a++)
189  *        {
190  *
191  *            result = MathUtils.typeConvert (
192  *                new BigDecimal (v1.doubleValue()).add (
193  *                new BigDecimal (v2.doubleValue())), v1, v2, false);
194  *
195  *        }
196  *
197  *        System.out.println ("took: "+(System.currentTimeMillis()-start));
198  *
199  *        start = System.currentTimeMillis();
200  *        for (int a = 0; a < 10000; a++)
201  *        {
202  *
203  *            result = MathUtils.divide( v1, v2);
204  *        }
205  *
206  *        Number result2 = result;
207  *        System.out.println ("took: "+(System.currentTimeMillis()-start));
208  *    }
209  *
210  */
211 
212     /**
213      * Test additional functions
214      */
215     public void testIsZero()
216     {
217         assertTrue (MathUtils.isZero (new Integer (0)));
218         assertTrue (!MathUtils.isZero (new Integer (1)));
219         assertTrue (!MathUtils.isZero (new Integer (-1)));
220 
221         assertTrue (MathUtils.isZero (new Float (0f)));
222         assertTrue (!MathUtils.isZero (new Float (0.00001f)));
223         assertTrue (!MathUtils.isZero (new Float (-0.00001f)));
224 
225     }
226 
227 }