1   /*
2    $Id: TestSupport.java,v 1.32 2004/04/19 07:29:46 cpoirier Exp $
3   
4    Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
5   
6    Redistribution and use of this software and associated documentation
7    ("Software"), with or without modification, are permitted provided
8    that the following conditions are met:
9   
10   1. Redistributions of source code must retain copyright
11      statements and notices.  Redistributions must also contain a
12      copy of this document.
13  
14   2. Redistributions in binary form must reproduce the
15      above copyright notice, this list of conditions and the
16      following disclaimer in the documentation and/or other
17      materials provided with the distribution.
18  
19   3. The name "groovy" must not be used to endorse or promote
20      products derived from this Software without prior written
21      permission of The Codehaus.  For written permission,
22      please contact info@codehaus.org.
23  
24   4. Products derived from this Software may not be called "groovy"
25      nor may "groovy" appear in their names without prior written
26      permission of The Codehaus. "groovy" is a registered
27      trademark of The Codehaus.
28  
29   5. Due credit should be given to The Codehaus -
30      http://groovy.codehaus.org/
31  
32   THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
33   ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
34   NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
35   FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
36   THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
37   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
43   OF THE POSSIBILITY OF SUCH DAMAGE.
44  
45   */
46  
47  package org.codehaus.groovy.classgen;
48  
49  import groovy.lang.Binding;
50  import groovy.lang.GroovyClassLoader;
51  import groovy.lang.GroovyCodeSource;
52  import groovy.lang.GroovyObject;
53  import groovy.lang.Script;
54  import groovy.util.GroovyTestCase;
55  
56  import java.beans.BeanInfo;
57  import java.beans.Introspector;
58  import java.beans.PropertyDescriptor;
59  import java.io.File;
60  import java.lang.reflect.Field;
61  import java.lang.reflect.InvocationTargetException;
62  import java.lang.reflect.Method;
63  import java.security.AccessController;
64  import java.security.PrivilegedAction;
65  
66  import org.codehaus.groovy.ast.ClassNode;
67  import org.codehaus.groovy.ast.CompileUnit;
68  import org.codehaus.groovy.ast.FieldNode;
69  import org.codehaus.groovy.ast.ModuleNode;
70  import org.codehaus.groovy.ast.expr.Expression;
71  import org.codehaus.groovy.ast.expr.FieldExpression;
72  import org.codehaus.groovy.ast.expr.MethodCallExpression;
73  import org.codehaus.groovy.ast.stmt.ExpressionStatement;
74  import org.codehaus.groovy.control.CompilerConfiguration;
75  import org.codehaus.groovy.runtime.InvokerHelper;
76  import org.objectweb.asm.Constants;
77  
78  /***
79   * Base class for test cases
80   * 
81   * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
82   * @version $Revision: 1.32 $
83   */
84  public class TestSupport extends GroovyTestCase implements Constants {
85  
86      protected static boolean DUMP_CLASS = false;
87  
88      // ClassLoader parentLoader = Thread.currentThread().getContextClassLoader();
89      ClassLoader parentLoader = getClass().getClassLoader();
90      protected GroovyClassLoader loader = 
91      	(GroovyClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
92      		public Object run() {
93      			return (DUMP_CLASS) 
94  					? new DumpingClassLoader(parentLoader)
95  					: new GroovyClassLoader(parentLoader); 
96      		}
97      	});
98      CompileUnit unit = new CompileUnit(parentLoader, new CompilerConfiguration());
99      ModuleNode module = new ModuleNode(unit);
100     
101     protected Class loadClass(ClassNode classNode) {
102         classNode.setModule(module);
103         Class fooClass = loader.defineClass(classNode, classNode.getName() + ".groovy", "groovy.testSupport");
104         return fooClass;
105     }
106 
107     protected void assertSetProperty(Object bean, String property, Object newValue) throws Exception {
108         PropertyDescriptor descriptor = getDescriptor(bean, property);
109         Method method = descriptor.getWriteMethod();
110         assertTrue("has setter method", method != null);
111 
112         Object[] args = { newValue };
113         Object value = invokeMethod(bean, method, args);
114 
115         assertEquals("should return null", null, value);
116 
117         assertGetProperty(bean, property, newValue);
118     }
119 
120     protected void assertGetProperty(Object bean, String property, Object expected) throws Exception {
121         PropertyDescriptor descriptor = getDescriptor(bean, property);
122         Method method = descriptor.getReadMethod();
123         assertTrue("has getter method", method != null);
124 
125         Object[] args = {
126         };
127         Object value = invokeMethod(bean, method, args);
128 
129         /*
130         System.out.println("Expected: " + expected);
131         System.out.println("Value: " + value);
132         
133         if (expected == null) { System.out.println("Expected is null"); }
134         if (value == null) { System.out.println("value is null"); }
135         */
136         
137         assertEquals("property value", expected, value);
138     }
139 
140     protected Object invokeMethod(Object bean, Method method, Object[] args) throws Exception {
141         try {
142             return method.invoke(bean, args);
143         }
144         catch (InvocationTargetException e) {
145             fail("InvocationTargetException: " + e.getTargetException());
146             return null;
147         }
148     }
149 
150     protected PropertyDescriptor getDescriptor(Object bean, String property) throws Exception {
151         BeanInfo info = Introspector.getBeanInfo(bean.getClass());
152         PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
153         for (int i = 0; i < descriptors.length; i++) {
154             PropertyDescriptor descriptor = descriptors[i];
155             if (descriptor.getName().equals(property)) {
156                 return descriptor;
157             }
158         }
159         fail("Could not find property: " + property + " on bean: " + bean);
160         return null;
161     }
162 
163     protected void assertField(Class aClass, String name, int modifiers, String typeName) throws Exception {
164         Field field = aClass.getDeclaredField(name);
165 
166         assertTrue("Found field called: " + name, field != null);
167         assertEquals("Name", name, field.getName());
168         assertEquals("Type", typeName, field.getType().getName());
169         assertEquals("Modifiers", modifiers, field.getModifiers());
170     }
171 
172     protected ExpressionStatement createPrintlnStatement(Expression expression) throws NoSuchFieldException {
173         return new ExpressionStatement(
174             new MethodCallExpression(
175                 new FieldExpression(FieldNode.newStatic(System.class, "out")),
176                 "println",
177                 expression));
178     }
179 
180     /***
181      * Asserts that the script runs without any exceptions
182      * @param script
183      */
184     protected void assertScript(String text) throws Exception {
185         assertScript(text, getTestClassName());
186     }
187     
188     protected void assertScript(final String text, final String scriptName) throws Exception {
189         log.info("About to execute script");
190         log.info(text);
191     	GroovyCodeSource gcs = (GroovyCodeSource) AccessController.doPrivileged(new PrivilegedAction() {
192     		public Object run() {
193     			return new GroovyCodeSource(text, scriptName, "/groovy/testSupport");
194     		}
195     	});
196         Class groovyClass = loader.parseClass(gcs);
197         Script script = InvokerHelper.createScript(groovyClass, new Binding());
198         script.run();
199     }
200     
201     protected void assertScriptFile(String fileName) throws Exception {
202         log.info("About to execute script: " + fileName);
203         
204         Class groovyClass = loader.parseClass(new GroovyCodeSource(new File(fileName)));
205         Script script = InvokerHelper.createScript(groovyClass, new Binding());
206         script.run();
207     }
208     
209     protected GroovyObject compile(String fileName) throws Exception {
210         Class groovyClass = loader.parseClass(new GroovyCodeSource(new File(fileName)));
211 
212         GroovyObject object = (GroovyObject) groovyClass.newInstance();
213 
214         assertTrue(object != null);
215 
216         return object;
217     }
218 }