Clover icon

magnolia-module-groovy 2.4.7

  1. Project Clover database Thu Dec 1 2016 10:48:40 CET
  2. Package info.magnolia.module.groovy.support.classes

File GroovyClassFactoryTest.java

 

Code metrics

0
100
16
1
312
209
18
0.18
6.25
16
1.12

Classes

Class Line # Actions
GroovyClassFactoryTest 62 100 0% 18 2
0.9827586498.3%
 

Contributing tests

This file is covered by 13 tests. .

Source view

1    /**
2    * This file Copyright (c) 2010-2016 Magnolia International
3    * Ltd. (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10    * This file is distributed in the hope that it will be
11    * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12    * implied warranty of MERCHANTABILITY or FITNESS FOR A
13    * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14    * Redistribution, except as permitted by whichever of the GPL
15    * or MNA you select, is prohibited.
16    *
17    * 1. For the GPL license (GPL), you can redistribute and/or
18    * modify this file under the terms of the GNU General
19    * Public License, Version 3, as published by the Free Software
20    * Foundation. You should have received a copy of the GNU
21    * General Public License, Version 3 along with this program;
22    * if not, write to the Free Software Foundation, Inc., 51
23    * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24    *
25    * 2. For the Magnolia Network Agreement (MNA), this file
26    * and the accompanying materials are made available under the
27    * terms of the MNA which accompanies this distribution, and
28    * is available at http://www.magnolia-cms.com/mna.html
29    *
30    * Any modifications to this file must keep this entire header
31    * intact.
32    *
33    */
34    package info.magnolia.module.groovy.support.classes;
35   
36    import static info.magnolia.module.groovy.GroovyModule.SCRIPTS_REPOSITORY_NAME;
37    import static org.junit.Assert.*;
38    import static org.mockito.Matchers.any;
39    import static org.mockito.Matchers.anyString;
40    import static org.mockito.Matchers.eq;
41    import static org.mockito.Mockito.*;
42   
43    import info.magnolia.context.MgnlContext;
44    import info.magnolia.context.SystemContext;
45    import info.magnolia.module.ModuleLifecycle;
46    import info.magnolia.module.groovy.GroovyBaseTestCase;
47    import info.magnolia.objectfactory.ClassFactory;
48    import info.magnolia.test.ComponentsTestUtil;
49    import info.magnolia.test.mock.jcr.SessionTestUtil;
50   
51    import java.util.Calendar;
52   
53    import javax.jcr.Node;
54    import javax.jcr.Session;
55   
56    import org.codehaus.groovy.control.CompilationFailedException;
57    import org.junit.Test;
58    import org.mockito.invocation.InvocationOnMock;
59    import org.mockito.stubbing.Answer;
60   
61   
 
62    public class GroovyClassFactoryTest extends GroovyBaseTestCase {
63   
64    private SystemContext context;
65    private Session session;
66    private GroovyClassFactory cf;
67   
 
68  13 toggle @Override
69    public void setUp() throws Exception {
70  13 super.setUp();
71  13 session = mock(Session.class);
72  13 context = mock(SystemContext.class);
73  13 when(context.getJCRSession(anyString())).thenReturn(session);
74  13 MgnlContext.setInstance(context);
75  13 ComponentsTestUtil.setInstance(SystemContext.class, context);
76  13 cf = new GroovyClassFactory();
77    }
78   
 
79  13 toggle @Override
80    public void tearDown() throws Exception {
81  13 super.tearDown();
82  13 MgnlContext.setInstance(null);
83  13 ComponentsTestUtil.setInstance(SystemContext.class, null);
84    }
85   
 
86  1 toggle @Test
87    public void delegateToDefaultClassFactoryToLoadJavaClasses() throws Exception {
88  1 final String className = "info.magnolia.module.groovy.trees.ScriptsAdminTreeConfig";
89   
90  1 final ClassFactory defaultCF = mock(ClassFactory.class);
91  1 when(defaultCF.forName(className)).thenReturn(null); // we don't really care about the return value
92   
93  1 final GroovyClassFactory cf = new GroovyClassFactory(defaultCF);
94  1 cf.forName(className);
95    }
96   
 
97  1 toggle @Test
98    public void throwRegularCNFEWhenClassExistsForNeitherCFs() throws Exception {
99  1 final String className = "non.existing.class";
100   
101  1 final ClassFactory defaultCF = mock(ClassFactory.class);
102  1 when(defaultCF.forName(className)).thenThrow(new ClassNotFoundException("ignored message"));
103   
104  1 when(context.getJCRSession(anyString())).thenReturn(session);
105  1 when(session.nodeExists(anyString())).thenReturn(false);
106   
107  1 try {
108  1 cf.forName(className);
109  0 fail("should have failed");
110    } catch (ClassNotFoundException e) {
111    // the default CF threw the exception with "ignored message", so by checking the message of the CNFE, we ensure it was thrown by the GroovyCL
112  1 assertEquals(className, e.getMessage());
113    }
114   
115    }
116   
 
117  1 toggle @Test
118    public void throwCNFEWithCompilationErrorWhenGroovyClassCanNotBeCompiled() throws Exception {
119  1 final String className = "info.magnolia.module.groovy.test.Buggy";
120   
121  1 final ClassFactory defaultCF = mock(ClassFactory.class);
122  1 when(defaultCF.forName(className)).thenThrow(new ClassNotFoundException("ignored message"));
123  1 when(session.nodeExists(anyString())).thenReturn(false);
124   
125  1 try {
126  1 cf.forName(className);
127  0 fail("should have failed");
128    } catch (ClassNotFoundException e) {
129  1 assertEquals("Could not compile " + className + " with Groovy", e.getMessage());
130  1 assertTrue(e.getCause() instanceof CompilationFailedException);
131  1 assertTrue("Actual cause message is: " + e.getCause().getMessage(), e.getCause().getMessage().contains("info.magnolia.non.existent.Foo"));
132    }
133    }
134   
 
135  1 toggle @Test
136    public void loadedGroovyClassesCanUseClassesFoundThroughTheDefaultClassLoader() throws Exception {
137  1 final String className = "info.magnolia.module.groovy.test.DummyGroovifiedModule";
138   
139  1 when(session.nodeExists(anyString())).thenReturn(false);
140   
141  1 final ClassFactory defaultCF = mock(ClassFactory.class);
142  1 when(defaultCF.forName(className)).thenThrow(new ClassNotFoundException("ignored message"));
143  1 when(defaultCF.newInstance(any(Class.class), any())).thenAnswer(new Answer<Object>() {
144   
 
145  1 toggle @Override
146    public Object answer(InvocationOnMock invocation) throws Throwable {
147  1 return ((Class) invocation.getArguments()[0]).newInstance();
148    }
149    });
150   
151   
152  1 final GroovyClassFactory cf = new GroovyClassFactory(defaultCF);
153  1 final Class cl = cf.forName(className);
154    // apparently Mockito can't handle the empty array argument that GCF passes to the mock, so here's a dummy argument
155  1 final ModuleLifecycle i = (ModuleLifecycle) cf.newInstance(cl, "dummy");
156  1 i.start(null);
157   
158    }
159   
 
160  1 toggle @Test
161    public void canLoadFromClassPath() throws Exception {
162  1 when(session.nodeExists("/info/magnolia/module/groovy/test/Dummy")).thenReturn(false);
163    // groovy-and/or-classloader try to load the beaninfo class... oh well.
164  1 when(session.nodeExists("/info/magnolia/module/groovy/test/DummyBeanInfo")).thenReturn(false);
165   
166  1 assertMethodCallOnNewInstance("woohoo", cf, "info.magnolia.module.groovy.test.Dummy", "value");
167    }
168   
 
169  1 toggle @Test
170    public void canLoadClassFromRepo() throws Exception {
171  1 final Session session = SessionTestUtil.createSession(SCRIPTS_REPOSITORY_NAME,
172    "/foo/bar/Baz.text=" + forProps(DUMMY_CLASS_STR_1) + "\n" +
173    "/foo/bar/Baz.language=groovy\n" +
174    "/foo/bar/Baz.enabled=boolean:true\n" +
175    "/foo/bar/Baz.mgnl\\:lastModified=date:2008-08-20T21:12:34.455+02:00\n");
176  1 when(context.getJCRSession(anyString())).thenReturn(session);
177   
178  1 assertMethodCallOnNewInstance("first value", cf, "foo.bar.Baz", "something");
179    }
180   
 
181  1 toggle @Test
182    public void repoHasPriorityOverClasspathIfScriptInRepoIsEnabled() throws Exception {
183    // GIVEN
184  1 Session session = SessionTestUtil.createSession(SCRIPTS_REPOSITORY_NAME, "/info/magnolia/module/groovy/test/Duplicate.text=" + forProps(DUPLICATE_CLASS_IN_REPO) + "\n" +
185    "/info/magnolia/module/groovy/test/Duplicate.language=groovy\n" +
186    "/info/magnolia/module/groovy/test/Duplicate.enabled=boolean:true\n" +
187    "/info/magnolia/module/groovy/test/Duplicate.mgnl\\:lastModified=date:2008-08-20T21:12:34.455+02:00\n");
188  1 when(context.getJCRSession(anyString())).thenReturn(session);
189    // WHEN
190    // THEN
191  1 assertMethodCallOnNewInstance("from repo", cf, "info.magnolia.module.groovy.test.Duplicate", "value");
192    }
193   
 
194  1 toggle @Test
195    public void fallBackToClassPathIfScriptInRepoIsDisabled() throws Exception {
196    // GIVEN
197  1 final Session session = SessionTestUtil.createSession(SCRIPTS_REPOSITORY_NAME,
198    "/info/magnolia/module/groovy/test/Duplicate.text=" + forProps(DUPLICATE_CLASS_IN_REPO) + "\n" +
199    "/info/magnolia/module/groovy/test/Duplicate.language=groovy\n" +
200    // no 'enabled' property is equal to enabled=false
201    "/info/magnolia/module/groovy/test/Duplicate.mgnl\\:lastModified=date:2008-08-20T21:12:34.455+02:00\n");
202  1 when(context.getJCRSession(anyString())).thenReturn(session);
203   
204    // WHEN
205    // THEN
206  1 assertMethodCallOnNewInstance("from classpath", cf, "info.magnolia.module.groovy.test.Duplicate", "value");
207    }
208   
 
209  1 toggle @Test
210    public void fallBackToClassPathIfScriptInRepoIsDisabledEvenIfScriptInRepoIsNewer() throws Exception {
211  1 final Session session = SessionTestUtil.createSession(SCRIPTS_REPOSITORY_NAME,
212    "/info/magnolia/module/groovy/test/Duplicate.text=" + forProps(DUPLICATE_CLASS_IN_REPO) + "\n" +
213    "/info/magnolia/module/groovy/test/Duplicate.language=groovy\n" +
214    "/info/magnolia/module/groovy/test/Duplicate.enabled=boolean:false\n" +
215    // guess nobody here will care if this test fails after 2888-08-20T21:12:34.455+02:00
216    "/info/magnolia/module/groovy/test/Duplicate.mgnl\\:lastModified=date:2888-08-20T21:12:34.455+02:00\n");
217  1 when(context.getJCRSession(anyString())).thenReturn(session);
218   
219  1 assertMethodCallOnNewInstance("from classpath", cf, "info.magnolia.module.groovy.test.Duplicate", "value");
220    }
221   
 
222  1 toggle @Test
223    public void recompileIfScriptInRepoWasModified() throws Exception {
224  1 final Session session = SessionTestUtil.createSession(SCRIPTS_REPOSITORY_NAME,
225    "/foo/bar/Baz.text=" + forProps(DUMMY_CLASS_STR_1) + "\n" +
226    "/foo/bar/Baz.language=groovy\n" +
227    "/foo/bar/Baz.enabled=boolean:true\n" +
228    // setting the lastModified here has no impact, since GroovyCL will compare the *compilation* with the "new source" to see if it has to recompile
229    "/foo/bar/Baz.mgnl\\:lastModified=date:2008-08-20T21:12:34.455+02:00\n");
230  1 when(context.getJCRSession(anyString())).thenReturn(session);
231   
232  1 assertMethodCallOnNewInstance("first value", cf, "foo.bar.Baz", "something");
233   
234    // now let's update the source
235  1 final Node node = session.getNode("/foo/bar/Baz");
236  1 node.getProperty("text").setValue(DUMMY_CLASS_STR_2);
237  1 final Calendar future = Calendar.getInstance();
238  1 future.add(Calendar.HOUR, 1); // can't use .getMetaData().setModificationDate(), we're too fast
239  1 node.getProperty("mgnl:lastModified").setValue(future);
240   
241  1 assertMethodCallOnNewInstance("new value", cf, "foo.bar.Baz", "something");
242    }
243   
 
244  1 toggle @Test
245    public void recompileOnNewInstanceIfScriptInRepoWasModified() throws Exception {
246  1 final Session session = SessionTestUtil.createSession(SCRIPTS_REPOSITORY_NAME,
247    "/foo/bar/Baz.text=" + forProps(DUMMY_CLASS_STR_1) + "\n" +
248    "/foo/bar/Baz.language=groovy\n" +
249    "/foo/bar/Baz.enabled=boolean:true\n" +
250    // setting the lastModified here has no impact, since GroovyCL will compare the *compilation* with the "new source" to see if it has to recompile
251    "/foo/bar/Baz.mgnl\\:lastModified=date:2008-08-20T21:12:34.455+02:00\n");
252  1 when(context.getJCRSession(anyString())).thenReturn(session);
253   
254  1 Class clazz = cf.forName("foo.bar.Baz");
255  1 Object baz = cf.newInstance(clazz);
256  1 Object aDifferentBazInstance = cf.newInstance(clazz);
257  1 Object retVal = baz.getClass().getMethod("something").invoke(baz);
258  1 Object retVal2 = aDifferentBazInstance.getClass().getMethod("something").invoke(aDifferentBazInstance);
259  1 assertEquals("first value", retVal);
260  1 assertEquals(retVal, retVal2);
261   
262    // now let's update the source
263  1 final Node node = session.getNode("/foo/bar/Baz");
264  1 node.getProperty("text").setValue(DUMMY_CLASS_STR_2);
265  1 final Calendar future = Calendar.getInstance();
266  1 future.add(Calendar.HOUR, 1); // can't use .getMetaData().setModificationDate(), we're too fast
267  1 node.getProperty("mgnl:lastModified").setValue(future);
268  1 Object aBrandNewBazInstance = cf.newInstance(clazz);
269  1 retVal = aBrandNewBazInstance.getClass().getMethod("something").invoke(aBrandNewBazInstance);
270  1 assertEquals("new value", retVal);
271    }
272   
 
273  1 toggle @Test
274    public void reloadRecompilesClassIfSourceChanged() throws Exception {
275  1 final Session session = SessionTestUtil.createSession(SCRIPTS_REPOSITORY_NAME,
276    "/foo/bar/Baz.text=" + forProps(DUMMY_CLASS_STR_1) + "\n" +
277    "/foo/bar/Baz.language=groovy\n" +
278    "/foo/bar/Baz.enabled=boolean:true\n" +
279    // setting the lastModified here has no impact, since GroovyCL will compare the *compilation* with the "new source" to see if it has to recompile
280    "/foo/bar/Baz.mgnl\\:lastModified=date:2008-08-20T21:12:34.455+02:00\n");
281   
282  1 when(context.getJCRSession(eq(SCRIPTS_REPOSITORY_NAME))).thenReturn(session);
283  1 Class clazz = cf.forName("foo.bar.Baz");
284   
285    // now let's update the source
286  1 final Node node = session.getNode("/foo/bar/Baz");
287  1 node.setProperty("text", DUMMY_CLASS_STR_2);
288  1 final Calendar future = Calendar.getInstance();
289  1 future.add(Calendar.HOUR, 1); // can't use .getMetaData().setModificationDate(), we're too fast
290  1 node.getProperty("mgnl:lastModified").setValue(future);
291  1 Class aNewClazz = cf.reload(clazz);
292   
293  1 assertNotEquals(aNewClazz, clazz);
294    }
295   
 
296  1 toggle @Test
297    public void reloadDoesNotRecompilesClassIfSourceUnchanged() throws Exception {
298  1 final Session session = SessionTestUtil.createSession(SCRIPTS_REPOSITORY_NAME,
299    "/foo/bar/Baz.text=" + forProps(DUMMY_CLASS_STR_1) + "\n" +
300    "/foo/bar/Baz.language=groovy\n" +
301    "/foo/bar/Baz.enabled=boolean:true\n" +
302    // setting the lastModified here has no impact, since GroovyCL will compare the *compilation* with the "new source" to see if it has to recompile
303    "/foo/bar/Baz.mgnl\\:lastModified=date:2008-08-20T21:12:34.455+02:00\n");
304  1 when(context.getJCRSession(eq(SCRIPTS_REPOSITORY_NAME))).thenReturn(session);
305   
306  1 Class clazz = cf.forName("foo.bar.Baz");
307   
308  1 Class result = cf.reload(clazz);
309   
310  1 assertEquals(result, clazz);
311    }
312    }