/*
* Copyright (C) 2014 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package retroweibo.processor;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assert_;
import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.testing.compile.JavaFileObjects;
import junit.framework.TestCase;
import org.apache.velocity.app.Velocity;
import java.net.URLClassLoader;
import retroweibo.RetroWeibo;
import retroweibo.processor.RetroWeiboProcessor;
/**
* Test that Velocity doesn't cause the processor to fail in unusual class-loading environments.
* It has a bunch of overengineered "managers" like LogManager and ResourceManager that it wants
* to load, and the ClassLoader that it uses to load them is the context class loader. If that
* loader sees a different copy of Velocity (even if it is the same version) then Velocity will
* fail to initialize.
*
* @author emcmanus@google.com (Éamonn McManus)
*/
public class VelocityClassLoaderTest extends TestCase {
/**
* Make a different ClassLoader that loads the same URLs as this one, and use it to compile
* an {@code @RetroWeibo} class. If Velocity loads its managers using the context class loader,
* and that loader is still the original one that loaded this test, then it will find the
* original copy of the Velocity classes rather than the one from the new loader, and fail.
*
* <p>This test assumes that the test class was loaded by a URLClassLoader and that that loader's
* URLs also include the Velocity classes.
*/
public void testClassLoaderHack() throws Exception {
URLClassLoader myLoader = (URLClassLoader) getClass().getClassLoader();
URLClassLoader newLoader = new URLClassLoader(myLoader.getURLs(), myLoader.getParent());
String velocityClassName = Velocity.class.getName();
Class<?> myVelocity = myLoader.loadClass(velocityClassName);
Class<?> newVelocity = newLoader.loadClass(velocityClassName);
assertThat(myVelocity).isNotEqualTo(newVelocity);
Runnable test = (Runnable) newLoader.loadClass(RunInClassLoader.class.getName()).newInstance();
assertThat(test.getClass()).isNotEqualTo(RunInClassLoader.class);
test.run();
}
public static class RunInClassLoader implements Runnable {
@Override
public void run() {
String source = Joiner.on('\n').join(ImmutableList.of(
"package foo.bar;",
"import " + RetroWeibo.class.getName() + ";",
"@RetroWeibo abstract class Test {",
" abstract int baz();",
" static Test create(int baz) {",
" return new RetroWeibo_Test(baz);",
" }",
"}"));
assert_().about(javaSource())
.that(JavaFileObjects.forSourceString("foo.bar.Test", source))
.processedWith(new RetroWeiboProcessor())
.compilesWithoutError();
}
}
}