Skip to content

Commit a039e61

Browse files
committed
Issue #1036: Adding unit test
1 parent 44222d8 commit a039e61

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

guice/src/test/java/cucumber/runtime/java/guice/impl/InjectorSourceFactoryTest.java

+65
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@
33
import com.google.inject.Injector;
44
import cucumber.runtime.Env;
55
import cucumber.runtime.java.guice.InjectorSource;
6+
import org.junit.Assert;
67
import org.junit.Test;
78

9+
import java.io.ByteArrayOutputStream;
10+
import java.io.File;
11+
import java.io.FileInputStream;
12+
import java.io.FileNotFoundException;
13+
import java.net.URL;
14+
import java.net.URLClassLoader;
815
import java.util.Properties;
916

1017
import static org.hamcrest.CoreMatchers.instanceOf;
@@ -110,4 +117,62 @@ public void failsToInstantiateClassWithNoDefaultConstructor() throws Exception {
110117
assertThat(exception.getCause(), instanceOf(InstantiationException.class));
111118
}
112119
}
120+
121+
/**
122+
* <p>Simulates enterprise applications which often use a hierarchy of classloaders.
123+
*
124+
* <p>MyChildClassLoader is the only classloader with knowledge of c.r.j.guice.impl.LivesInChildClassLoader
125+
*
126+
* <p>The bytecode of LivesInChildClassLoader is intentionally renamed to 'LivesInChildClassLoader.class.txt' to prevent
127+
* this test's ClassLoader from resolving it.
128+
*
129+
* <p>If InjectorSourceFactory calls Class#forName without an explicit ClassLoader argument, which is the behavior of
130+
* 1.2.4 and earlier, Class#forName will default to the test's ClassLoader which has no knowledge
131+
* of class LivesInChildClassLoader and the test will fail.
132+
*
133+
* <p>See <a href="https://github.com/cucumber/cucumber-jvm/issues/1036">https://github.com/cucumber/cucumber-jvm/issues/1036</a>
134+
* @throws Exception
135+
*/
136+
@Test
137+
public void instantiateClassInChildClassLoader() throws Exception {
138+
ClassLoader childClassLoader = new MyChildClassLoader(this.getClass().getClassLoader());
139+
Thread.currentThread().setContextClassLoader( childClassLoader );
140+
141+
Properties properties = new Properties();
142+
properties.setProperty(InjectorSourceFactory.GUICE_INJECTOR_SOURCE_KEY, "cucumber.runtime.java.guice.impl.LivesInChildClassLoader");
143+
InjectorSourceFactory injectorSourceFactory = createInjectorSourceFactory(properties);
144+
145+
assertThat(injectorSourceFactory.create(), is(instanceOf(InjectorSource.class)));
146+
}
147+
148+
private static class MyChildClassLoader extends ClassLoader {
149+
public MyChildClassLoader( ClassLoader parent ) {
150+
super(parent);
151+
}
152+
153+
@Override
154+
protected Class<?> loadClass( String name, boolean resolve ) throws ClassNotFoundException {
155+
if( name.equals( "cucumber.runtime.java.guice.impl.LivesInChildClassLoader" ) ) {
156+
String filename = getClass().getClassLoader().getResource("cucumber/runtime/java/guice/impl/LivesInChildClassLoader.class.txt").getFile();
157+
File file = new File( filename );
158+
try {
159+
FileInputStream in = new FileInputStream( file );
160+
byte[] bytes = new byte[1024];
161+
ByteArrayOutputStream content = new ByteArrayOutputStream();
162+
while( true ) {
163+
int iLen = in.read(bytes);
164+
content.write( bytes, 0, iLen );
165+
if( iLen < 1024 ) {
166+
break;
167+
}
168+
}
169+
byte[] bytecode = content.toByteArray();
170+
return defineClass( name, bytecode, 0, bytecode.length );
171+
} catch (Exception e) {
172+
throw new RuntimeException( e );
173+
}
174+
}
175+
return super.loadClass(name, resolve);
176+
}
177+
}
113178
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package cucumber.runtime.java.guice.impl;
2+
3+
import com.google.inject.Injector;
4+
import cucumber.runtime.java.guice.InjectorSource;
5+
6+
public class LivesInChildClassLoader implements InjectorSource {
7+
@Override
8+
public Injector getInjector() {
9+
return null;
10+
}
11+
}

0 commit comments

Comments
 (0)