View Javadoc

1   // Copyright (C) 2011 - 2012 Philip Aston
2   // All rights reserved.
3   //
4   // This file is part of The Grinder software distribution. Refer to
5   // the file LICENSE which is part of The Grinder distribution for
6   // licensing details. The Grinder distribution is available on the
7   // Internet at http://grinder.sourceforge.net/
8   //
9   // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
12  // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
13  // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
14  // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
15  // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
17  // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
18  // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
19  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
20  // OF THE POSSIBILITY OF SUCH DAMAGE.
21  
22  package net.grinder.engine.process;
23  
24  import static java.util.Arrays.asList;
25  import static junit.framework.Assert.assertEquals;
26  import static net.grinder.testutility.AssertUtilities.assertContains;
27  import static net.grinder.testutility.FileUtilities.createFile;
28  import static org.junit.Assert.assertTrue;
29  import static org.junit.Assert.fail;
30  
31  import java.io.File;
32  import java.io.IOException;
33  import java.lang.reflect.InvocationTargetException;
34  import java.lang.reflect.Method;
35  import java.net.URL;
36  import java.util.Collections;
37  import java.util.Enumeration;
38  import java.util.HashSet;
39  import java.util.List;
40  
41  import net.grinder.common.GrinderProperties;
42  import net.grinder.engine.common.EngineException;
43  import net.grinder.engine.common.ScriptLocation;
44  import net.grinder.scriptengine.DCRContext;
45  import net.grinder.scriptengine.Instrumenter;
46  import net.grinder.scriptengine.ScriptEngineService;
47  import net.grinder.scriptengine.ScriptEngineService.ScriptEngine;
48  import net.grinder.testutility.AbstractJUnit4FileTestCase;
49  import net.grinder.util.BlockingClassLoader;
50  import net.grinder.util.Directory;
51  
52  import org.junit.Before;
53  import org.junit.Test;
54  import org.mockito.Mock;
55  import org.mockito.MockitoAnnotations;
56  import org.slf4j.Logger;
57  
58  
59  /**
60   * Unit tests for {@link ScriptEngineContainer}.
61   *
62   * @author Philip Aston
63   */
64  public class TestScriptEngineContainer extends AbstractJUnit4FileTestCase {
65  
66    @Mock private DCRContext m_dcrContext;
67    @Mock private GrinderProperties m_properties;
68    @Mock private Logger m_logger;
69  
70    private ScriptLocation m_pyScript;
71  
72    @Before public void initialise() throws Exception {
73      MockitoAnnotations.initMocks(this);
74      m_pyScript = new ScriptLocation(new File("foo.py"));
75    }
76  
77    @Test public void testBadResourceLoading() throws Exception {
78      final ClassLoader blockingLoader =
79        new BlockingClassLoader(
80           Collections.<String>emptySet(),
81           new HashSet<String>(
82               asList(ScriptEngineContainer.class.getName(),
83                      ScriptEngineContainerScopeTunnel.class.getName(),
84                      ScriptEngineService.class.getName())),
85           Collections.<String>emptySet(),
86           false) {
87          @Override public Enumeration<URL> getResources(String name)
88            throws IOException {
89            // Be evil.
90            throw new IOException("");
91          }
92        };
93  
94      try {
95        constructInClassLoader(blockingLoader);
96        fail("Expected EngineException");
97      }
98      catch (InvocationTargetException e) {
99        assertTrue(e.getCause() instanceof EngineException);
100     }
101   }
102 
103   private final void constructInClassLoader(ClassLoader loader)
104     throws Exception {
105 
106     final Class<?> c =
107       loader.loadClass(ScriptEngineContainerScopeTunnel.class.getName());
108 
109     final Method method =
110       c.getMethod("createScriptEngineContainer",
111                   GrinderProperties.class,
112                   Logger.class,
113                   DCRContext.class,
114                   ScriptLocation.class);
115 
116     method.invoke(null, m_properties, m_logger, m_dcrContext, m_pyScript);
117   }
118 
119   @Test public void testUnknownImplementation() throws Exception {
120 
121     final File path = new File(getDirectory(), "cp");
122 
123     createFile(new File(path, ScriptEngineService.RESOURCE_NAME),
124                "bobbins");
125 
126     final List<URL> additionalClasspath =
127       asList(new File(getDirectory(), "cp").toURI().toURL());
128 
129     final ClassLoader blockingLoader =
130       new BlockingClassLoader(
131          additionalClasspath,
132          Collections.<String>emptySet(),
133          new HashSet<String>(
134              asList(ScriptEngineContainer.class.getName(),
135                     ScriptEngineContainerScopeTunnel.class.getName(),
136                     ScriptEngineService.class.getName(),
137                     ScriptEngineService.RESOURCE_NAME)),
138          Collections.<String>emptySet(),
139          true);
140 
141     try {
142       constructInClassLoader(blockingLoader);
143       fail("Expected EngineException");
144     }
145     catch (InvocationTargetException e) {
146       assertTrue(e.getCause() instanceof EngineException);
147       assertTrue(e.getCause().getCause() instanceof ClassNotFoundException);
148     }
149   }
150 
151   @Test public void testBadImplementation() throws Exception {
152 
153     final File path = new File(getDirectory(), "cp");
154 
155     createFile(new File(path, ScriptEngineService.RESOURCE_NAME),
156                "java.lang.Object");
157 
158     final List<URL> additionalClasspath =
159       asList(new File(getDirectory(), "cp").toURI().toURL());
160 
161     final ClassLoader blockingLoader =
162       new BlockingClassLoader(
163          additionalClasspath,
164          Collections.<String>emptySet(),
165          new HashSet<String>(
166            asList(ScriptEngineContainer.class.getName(),
167                   ScriptEngineContainerScopeTunnel.class.getName(),
168                   ScriptEngineService.class.getName(),
169                   ScriptEngineService.RESOURCE_NAME)),
170          Collections.<String>emptySet(),
171          true);
172 
173     try {
174       constructInClassLoader(blockingLoader);
175       fail("Expected EngineException");
176     }
177     catch (InvocationTargetException e) {
178       assertTrue(e.getCause() instanceof EngineException);
179       assertContains(e.getCause().getMessage(), "does not implement");
180     }
181   }
182 
183   @Test public void testStandardInstrumentationNoDCR() throws Exception {
184     final ScriptEngineContainer container =
185       new ScriptEngineContainer(m_properties, m_logger, null, m_pyScript);
186 
187     final Instrumenter instrumenter = container.createInstrumenter();
188     assertEquals("NO INSTRUMENTER COULD BE LOADED",
189                  instrumenter.getDescription());
190   }
191 
192   @Test public void testStandardInstrumentationDCR() throws Exception {
193     final ScriptEngineContainer container =
194       new ScriptEngineContainer(m_properties,
195                                 m_logger,
196                                 m_dcrContext,
197                                 m_pyScript);
198 
199     final Instrumenter instrumenter = container.createInstrumenter();
200     assertEquals("byte code transforming instrumenter for Jython 2.5; " +
201                  "byte code transforming instrumenter for Java",
202                  instrumenter.getDescription());
203   }
204 
205   @Test public void testUnknownScriptType() throws Exception {
206     final ScriptEngineContainer container =
207       new ScriptEngineContainer(m_properties,
208                                 m_logger,
209                                 m_dcrContext,
210                                 m_pyScript);
211 
212     try {
213       container.getScriptEngine(new ScriptLocation(new File("foo.xxx")));
214       fail("Expected EngineException");
215     }
216     catch (EngineException e) {
217       assertContains(e.getMessage(), "No suitable script engine");
218     }
219   }
220 
221   @Test public void testJythonScript() throws Exception {
222     final ScriptLocation pyScript =
223       new ScriptLocation(new Directory(getDirectory()),
224                          new File("my.py"));
225 
226     createFile(pyScript.getFile(),
227                "class TestRunner: pass");
228 
229     final ScriptEngineContainer container =
230       new ScriptEngineContainer(m_properties,
231                                 m_logger,
232                                 m_dcrContext,
233                                 m_pyScript);
234 
235     final ScriptEngine scriptEngine = container.getScriptEngine(pyScript);
236     assertContains(scriptEngine.getDescription(), "Jython");
237   }
238 }