001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tctest;
005:
006: import com.tc.exception.TCRuntimeException;
007: import com.tc.object.TCObject;
008: import com.tc.object.bytecode.ByteCodeUtil;
009: import com.tc.object.config.ConfigVisitor;
010: import com.tc.object.config.DSOClientConfigHelper;
011: import com.tc.simulator.app.ApplicationConfig;
012: import com.tc.simulator.listener.ListenerProvider;
013: import com.tctest.runner.AbstractTransparentApp;
014:
015: import java.lang.reflect.Constructor;
016: import java.lang.reflect.Field;
017: import java.lang.reflect.InvocationTargetException;
018: import java.lang.reflect.Method;
019: import java.lang.reflect.Modifier;
020: import java.math.BigDecimal;
021: import java.math.BigInteger;
022: import java.util.Random;
023:
024: /*
025: * Test cases for testing method invocations for BigInteger and BigDecimal classes.
026: * Testcases for testing the sharing of BigInteger and BigDecimal objects are handled by
027: * TransparentTestApp.
028: */
029: public class BigIntegerDecimalTestApp extends AbstractTransparentApp {
030: private final static BigInteger refInt = new BigInteger("100");
031: private final static BigDecimal refDecimal = new BigDecimal("100.0");
032:
033: public BigIntegerDecimalTestApp(String appId,
034: ApplicationConfig cfg, ListenerProvider listenerProvider) {
035: super (appId, cfg, listenerProvider);
036: }
037:
038: public void run() {
039: runBigIntegerTests();
040: runBigDecimalTests();
041: }
042:
043: private void runBigIntegerTests() {
044: System.out
045: .println("==========BigInteger tests Begin.==========");
046: invokeAllBigIntegerConstructors();
047: invokeAllBigIntegerMethods();
048: System.out.println("==========BigInteger tests End.==========");
049: }
050:
051: private void runBigDecimalTests() {
052: System.out
053: .println("==========BigDecimal tests Begin.==========");
054: invokeAllBigDecimalConstructors();
055: invokeAllBigDecimalMethods();
056: System.out.println("==========BigDecimal tests End.==========");
057: }
058:
059: private void invokeAllBigDecimalMethods() {
060: invokeAllMethods(BigDecimal.class, false);
061: invokeAllMethods(BigDecimal.class, true);
062: }
063:
064: private void invokeAllBigIntegerMethods() {
065: invokeAllMethods(BigInteger.class, false);
066: invokeAllMethods(BigInteger.class, true);
067: }
068:
069: private void invokeAllMethods(Class bClazz, boolean lock) {
070: Object[] methodArguments = null;
071: Object object = null;
072:
073: boolean bigIntegerClass = false;
074: if (bClazz.equals(BigInteger.class)) {
075: bigIntegerClass = true;
076: }
077:
078: Method[] methods = bClazz.getDeclaredMethods();
079: for (int i = 0; i < methods.length; i++) {
080: try {
081: if (!Modifier.isPrivate(methods[i].getModifiers())
082: && !methods[i].getName().startsWith(
083: ByteCodeUtil.TC_METHOD_PREFIX)
084: && !methods[i].getName().endsWith("class$")) {
085: System.out.println("Executing method: "
086: + methods[i].getName());
087: if (!Modifier.isPublic(methods[i].getModifiers())) {
088: methods[i].setAccessible(true);
089: }
090:
091: methodArguments = bigIntegerClass ? getBigIntegerMethodArguments(methods[i])
092: : getBigDecimalMethodArguments(methods[i]);
093:
094: if (bigIntegerClass) {
095: object = new BigInteger("101");
096: } else {
097: object = new BigDecimal("101.0");
098: }
099:
100: invokeMethod(object, methods[i], methodArguments,
101: lock);
102: }
103: } catch (IllegalArgumentException e) {
104: throw new TCRuntimeException(e);
105: } catch (IllegalAccessException e) {
106: throw new TCRuntimeException(e);
107: } catch (InvocationTargetException e) {
108: throw new TCRuntimeException(e);
109: }
110: }
111: }
112:
113: private void invokeMethod(Object object, Method method,
114: Object[] methodArguments, boolean lock)
115: throws IllegalArgumentException, IllegalAccessException,
116: InvocationTargetException {
117: if (lock) {
118: synchronized (object) {
119: method.invoke(object, methodArguments);
120: }
121: } else {
122: method.invoke(object, methodArguments);
123: }
124: }
125:
126: // Brute force for getting the arguments for an BigDecimal method.
127: private Object[] getBigDecimalMethodArguments(Method method) {
128: Class[] parameterTypes = method.getParameterTypes();
129: Object[] arguments = new Object[parameterTypes.length];
130: String methodName = method.getName();
131:
132: Class mathContextClazz = getMathContextClass();
133: Object decimal32MathContext = getDecimal32MathContext(mathContextClazz);
134:
135: Class roundingModeClazz = getRoundingModeClass();
136: Object upRoundingMode = getUpRoundingMode(roundingModeClazz);
137:
138: if (("abs".equals(methodName) || "negate".equals(methodName) || "plus"
139: .equals(methodName))
140: && arguments.length == 1) {
141: if (parameterTypes[0].equals(mathContextClazz)) {
142: arguments[0] = decimal32MathContext;
143: }
144: } else if ("add".equals(methodName)) {
145: arguments[0] = refDecimal;
146: if (arguments.length == 2
147: && parameterTypes[1].equals(mathContextClazz)) {
148: arguments[1] = decimal32MathContext;
149: }
150: } else if ("compareTo".equals(methodName)
151: || "equals".equals(methodName)
152: || "max".equals(methodName) || "min".equals(methodName)) {
153: arguments[0] = refDecimal;
154: } else if ("divide".equals(methodName)
155: || "multiply".equals(methodName)
156: || "subtract".equals(methodName)) {
157: arguments[0] = refDecimal;
158: if (arguments.length == 2) {
159: if (parameterTypes[1].equals(mathContextClazz)) {
160: arguments[1] = decimal32MathContext;
161: } else if (parameterTypes[1].equals(roundingModeClazz)) {
162: arguments[1] = upRoundingMode;
163: } else {
164: arguments[1] = new Integer(BigDecimal.ROUND_UP);
165: }
166: } else if (arguments.length == 3) {
167: arguments[1] = new Integer(1);
168: if (parameterTypes[2].equals(roundingModeClazz)) {
169: arguments[2] = upRoundingMode;
170: } else {
171: arguments[2] = new Integer(BigDecimal.ROUND_UP);
172: }
173: }
174: } else if ("divideAndRemainder".equals(methodName)
175: || "divideToIntegralValue".equals(methodName)
176: || "remainder".equals(methodName)) {
177: arguments[0] = refDecimal;
178: if (arguments.length == 2
179: && parameterTypes[1].equals(mathContextClazz)) {
180: arguments[1] = decimal32MathContext;
181: }
182: } else if ("movePointLeft".equals(methodName)
183: || "movePointRight".equals(methodName)
184: || "scaleByPowerOfTen".equals(methodName)) {
185: arguments[0] = new Integer(1);
186: } else if ("pow".equals(methodName)) {
187: arguments[0] = new Integer(1);
188: if (arguments.length == 2
189: && parameterTypes[1].equals(mathContextClazz)) {
190: arguments[1] = decimal32MathContext;
191: }
192: } else if ("round".equals(methodName)) {
193: arguments[0] = decimal32MathContext;
194: } else if ("setScale".equals(methodName)) {
195: arguments[0] = new Integer(1);
196: if (arguments.length == 2) {
197: if (parameterTypes[1].equals(roundingModeClazz)) {
198: arguments[1] = upRoundingMode;
199: } else {
200: arguments[1] = new Integer(BigDecimal.ROUND_UP);
201: }
202: }
203: } else if ("valueOf".equals(methodName)) {
204: if (parameterTypes[0].equals(Double.TYPE)) {
205: arguments[0] = new Double(100.0);
206: } else if (parameterTypes[0].equals(Long.TYPE)) {
207: arguments[0] = new Long(100);
208: if (arguments.length == 2) {
209: arguments[1] = new Integer(1);
210: }
211: }
212: }
213:
214: return arguments;
215: }
216:
217: // Brute force for getting the arguments for an BigInteger method.
218: private Object[] getBigIntegerMethodArguments(Method method) {
219: Object[] arguments = new Object[method.getParameterTypes().length];
220: String methodName = method.getName();
221: if ("add".equals(methodName) || "and".equals(methodName)
222: || "andNot".equals(methodName)) {
223: arguments[0] = new BigInteger("200");
224: } else if ("clearBit".equals(methodName)) {
225: arguments[0] = new Integer(1);
226: } else if ("compareTo".equals(methodName)
227: || "divide".equals(methodName)
228: || "divideAndRemainder".equals(methodName)
229: || "equals".equals(methodName)
230: || "gcd".equals(methodName) || "max".equals(methodName)
231: || "min".equals(methodName) || "mod".equals(methodName)
232: || "modInverse".equals(methodName)
233: || "multiply".equals(methodName)
234: || "or".equals(methodName)
235: || "remainder".equals(methodName)
236: || "subtract".equals(methodName)
237: || "xor".equals(methodName)) {
238: arguments[0] = refInt;
239: } else if ("flipBit".equals(methodName)
240: || "isProbablePrime".equals(methodName)
241: || "pow".equals(methodName)
242: || "setBit".equals(methodName)
243: || "shiftLeft".equals(methodName)
244: || "shiftRight".equals(methodName)
245: || "testBit".equals(methodName)
246: || "trailingZeroCnt".equals(methodName)
247: || "bitLen".equals(methodName)
248: || "primeToCertainty".equals(methodName)
249: || "bitCnt".equals(methodName)) {
250: arguments[0] = new Integer(1);
251: } else if ("modPow".equals(methodName)) {
252: arguments[0] = refInt;
253: arguments[1] = refInt;
254: } else if ("probablePrime".equals(methodName)) {
255: arguments[0] = new Integer(5);
256: arguments[1] = new Random();
257: } else if ("toString".equals(methodName)
258: && arguments.length == 1) {
259: arguments[0] = new Integer(1);
260: } else if ("valueOf".equals(methodName)) {
261: arguments[0] = new Long(1);
262: } else if ("mulAdd".equals(methodName)) {
263: arguments[0] = new int[] { 1 };
264: arguments[1] = new int[] { 1 };
265: arguments[2] = new Integer(0);
266: arguments[3] = new Integer(1);
267: arguments[4] = new Integer(1);
268: } else if ("addOne".equals(methodName)) {
269: arguments[0] = new int[] { 1 };
270: arguments[1] = new Integer(0);
271: arguments[2] = new Integer(0);
272: arguments[3] = new Integer(1);
273: } else if ("primitiveLeftShift".equals(methodName)
274: || "primitiveRightShift".equals(methodName)) {
275: arguments[0] = new int[] { 1 };
276: arguments[1] = new Integer(1);
277: arguments[2] = new Integer(1);
278: } else if ("javaIncrement".equals(methodName)) {
279: arguments[0] = new int[] { 1 };
280: } else if ("jacobiSymbol".equals(methodName)) {
281: arguments[0] = new Integer(1);
282: arguments[1] = refInt;
283: }
284:
285: return arguments;
286: }
287:
288: private void invokeAllBigDecimalConstructors() {
289: invokeAllConstructors(BigDecimal.class);
290: }
291:
292: private void invokeAllBigIntegerConstructors() {
293: invokeAllConstructors(BigInteger.class);
294: }
295:
296: private void invokeAllConstructors(Class bClazz) {
297: boolean bigIntegerClass = false;
298: if (bClazz.equals(BigInteger.class)) {
299: bigIntegerClass = true;
300: }
301: Object[] arguments = null;
302: Constructor[] constructors = bClazz.getConstructors();
303: for (int i = 0; i < constructors.length; i++) {
304: try {
305: arguments = (bigIntegerClass) ? getBigIntegerConstructorArguments(constructors[i]
306: .getParameterTypes())
307: : getBigDecimalConstructorArguments(constructors[i]
308: .getParameterTypes());
309: invokeConstructor(constructors[i], arguments);
310: } catch (IllegalArgumentException e) {
311: throw new TCRuntimeException(e);
312: } catch (InstantiationException e) {
313: throw new TCRuntimeException(e);
314: } catch (IllegalAccessException e) {
315: throw new TCRuntimeException(e);
316: } catch (InvocationTargetException e) {
317: throw new TCRuntimeException(e);
318: }
319: }
320: }
321:
322: private void invokeConstructor(Constructor constructor,
323: Object[] arguments) throws IllegalArgumentException,
324: InstantiationException, IllegalAccessException,
325: InvocationTargetException {
326: Class[] parameterTypes = constructor.getParameterTypes();
327: if (parameterTypes[0] != TCObject.class) {
328: constructor.newInstance(arguments);
329: }
330: }
331:
332: private Object[] getBigDecimalConstructorArguments(
333: Class[] parameterTypes) {
334: Class mathContextClazz = getMathContextClass();
335: Object decimal32MathContext = getDecimal32MathContext(mathContextClazz);
336:
337: Object[] arguments = new Object[parameterTypes.length];
338: if (parameterTypes[0].equals(BigInteger.class)) {
339: arguments[0] = new BigInteger("100");
340: if (parameterTypes.length == 2) {
341: if (parameterTypes[1].equals(mathContextClazz)) {
342: arguments[1] = decimal32MathContext;
343: } else {
344: arguments[1] = new Integer(1);
345: }
346: } else if (parameterTypes.length == 3) {
347: arguments[1] = new Integer(1);
348: arguments[2] = decimal32MathContext;
349: }
350: } else if (parameterTypes[0].equals(char[].class)) {
351: arguments[0] = new char[] { '1' };
352: if (parameterTypes.length == 2) {
353: arguments[1] = decimal32MathContext;
354: } else if (parameterTypes.length == 3) {
355: arguments[1] = new Integer(0);
356: arguments[2] = new Integer(1);
357: } else if (parameterTypes.length == 4) {
358: arguments[1] = new Integer(0);
359: arguments[2] = new Integer(1);
360: arguments[3] = decimal32MathContext;
361: }
362: } else if (parameterTypes[0].equals(Double.TYPE)) {
363: arguments[0] = new Double(100.0);
364: if (parameterTypes.length == 2) {
365: arguments[1] = decimal32MathContext;
366: }
367: } else if (parameterTypes[0].equals(Integer.TYPE)) {
368: arguments[0] = new Integer(100);
369: if (parameterTypes.length == 2) {
370: arguments[1] = decimal32MathContext;
371: }
372: } else if (parameterTypes[0].equals(Long.TYPE)) {
373: arguments[0] = new Long(100);
374: if (parameterTypes.length == 2) {
375: arguments[1] = decimal32MathContext;
376: }
377: } else if (parameterTypes[0].equals(String.class)) {
378: arguments[0] = "100.0";
379: if (parameterTypes.length == 2) {
380: arguments[1] = decimal32MathContext;
381: }
382: }
383:
384: return arguments;
385: }
386:
387: private Object[] getBigIntegerConstructorArguments(
388: Class[] parameterTypes) {
389: Object[] arguments = new Object[parameterTypes.length];
390: switch (parameterTypes.length) {
391: case 1:
392: if (parameterTypes[0] == String.class) {
393: arguments[0] = "100";
394: } else {
395: arguments[0] = new byte[] { (byte) 100 };
396: }
397: break;
398: case 2:
399: if (parameterTypes[0] == String.class) {
400: arguments[0] = "100";
401: arguments[1] = new Integer(10);
402: } else if (parameterTypes[1] == Random.class) {
403: arguments[0] = new Integer(10);
404: arguments[1] = new Random();
405: } else {
406: arguments[0] = new Integer(refInt.signum());
407: arguments[1] = new byte[] { (byte) 100 };
408: }
409: break;
410: case 3:
411: arguments[0] = new Integer(refInt.bitLength());
412: arguments[1] = new Integer(5);
413: arguments[2] = new Random();
414: break;
415: }
416:
417: return arguments;
418: }
419:
420: private Class getRoundingModeClass() {
421: return getClazz("java.math.RoundingMode");
422: }
423:
424: private Class getMathContextClass() {
425: return getClazz("java.math.MathContext");
426: }
427:
428: /*
429: * We need to use reflection to obtain class for RoundingMode and MathContext because
430: * these two classes do not exist in jdk1.4.
431: */
432: private Class getClazz(String className) {
433: Class mathContextClazz = null;
434: try {
435: mathContextClazz = Class.forName(className);
436: } catch (ClassNotFoundException e) {
437: // ignore ClassNotFoundException
438: } catch (SecurityException e) {
439: // ignore SecurityException
440: }
441: return mathContextClazz;
442: }
443:
444: private Object getUpRoundingMode(Class roundingModeClazz) {
445: return getField(roundingModeClazz, "UP");
446: }
447:
448: private Object getDecimal32MathContext(Class mathContextClazz) {
449: return getField(mathContextClazz, "DECIMAL32");
450: }
451:
452: /*
453: * We need to use reflection to obtain the UP and DECIMAL32 fields of class RoundingMode
454: * and MathContext because these two classes do not exist in jdk1.4.
455: */
456: private Object getField(Class mathContextClazz, String fieldName) {
457: if (mathContextClazz == null)
458: return null;
459: Object decimal32MathContext = null;
460: try {
461: Field decimal32Field = mathContextClazz
462: .getDeclaredField(fieldName);
463: decimal32MathContext = decimal32Field.get(null);
464: } catch (SecurityException e) {
465: // ignore SecurityException
466: } catch (NoSuchFieldException e) {
467: // ignore NoSuchFieldException
468: } catch (IllegalArgumentException e) {
469: // ignore IllegalArgumentException
470: } catch (IllegalAccessException e) {
471: // ignore IllegalAccessException
472: }
473: return decimal32MathContext;
474: }
475:
476: public static void visitL1DSOConfig(ConfigVisitor visitor,
477: DSOClientConfigHelper config) {
478: String testClass = BigIntegerDecimalTestApp.class.getName();
479: config.getOrCreateSpec(testClass);
480: String readOnlyMethodExpression = "* " + testClass
481: + "*.*ReadOnly*(..)";
482: config.addReadAutolock(readOnlyMethodExpression);
483: String writeAllowedMethodExpression = "* " + testClass
484: + "*.*(..)";
485: config.addWriteAutolock(writeAllowedMethodExpression);
486: }
487: }
|