/*
* Copyright 2010-2012 VMware and contributors
*
* 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 org.springsource.loaded.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.objectweb.asm.ClassReader;
import org.springsource.loaded.GlobalConfiguration;
import org.springsource.loaded.Plugins;
import org.springsource.loaded.ReloadEventProcessorPlugin;
import org.springsource.loaded.ReloadableType;
import org.springsource.loaded.TypeRegistry;
import org.springsource.loaded.agent.ClassVisitingConstructorAppender;
import org.springsource.loaded.test.infra.TestClassloaderWithRewriting;
/**
* Test the plugins (built in and user definable)
*
* @author Andy Clement
* @since 1.0
*/
public class PluginTests extends SpringLoadedTests {
@Before
public void setUp() throws Exception {
super.setup();
GlobalConfiguration.reloadMessages = true;
}
@After
public void tearDown() throws Exception {
super.teardown();
ensureCaptureOff();
GlobalConfiguration.reloadMessages = false;
}
@Test
public void constructorAppender() throws Exception {
ClassReader cr = new ClassReader(loadBytesForClass("plugins.One"));
Target.reset();
ClassVisitingConstructorAppender ca = new ClassVisitingConstructorAppender(Target.class.getName().replace('.', '/'), "foo");
cr.accept(ca, 0);
byte[] newbytes = ca.getBytes();
Class<?> clazz = loadit("plugins.One", newbytes);
clazz.newInstance();
List<Object> instances = Target.collectedInstances;
assertEquals(1, instances.size());
assertTrue(instances.get(0).toString().startsWith("plugins.One"));
Target.reset();
clazz.getDeclaredConstructor(String.class, Integer.TYPE).newInstance("abc", 32);
instances = Target.collectedInstances;
assertEquals(1, instances.size());
assertTrue(instances.get(0).toString().startsWith("plugins.One"));
clazz.getDeclaredMethod("run").invoke(instances.get(0));
}
// Test a simple plugin that processes reload events
@Test
public void testSimplePlugin() throws Exception {
binLoader = new TestClassloaderWithRewriting("meta1", true);
String t = "simple.Basic";
captureOn();
TypeRegistry r = getTypeRegistry(t);
String output = captureOff();
assertContains("Instantiated ReloadEventProcessorPlugin1", output);
ReloadableType rtype = r.addType(t, loadBytesForClass(t));
result = runUnguarded(rtype.getClazz(), "run");
assertEquals("hello", result.returnValue);
captureOn();
rtype.loadNewVersion("2", retrieveRename(t, t + "2"));
output = captureOff();
assertContains("Reloading: Loading new version of simple.Basic [2]", output);
assertContains("ReloadEventProcessorPlugin1: reloadEvent(simple.Basic,simple.Basic,2)", output);
result = runUnguarded(rtype.getClazz(), "run");
assertEquals("goodbye", result.returnValue);
}
// Test a simple plugin that processes reload events
@Test
public void testSimplePluginWithUnableToReloadEvent() throws Exception {
binLoader = new TestClassloaderWithRewriting("meta1", true);
String t = "simple.Basic";
captureOn();
TypeRegistry r = getTypeRegistry(t);
String output = captureOff();
assertContains("Instantiated ReloadEventProcessorPlugin1", output);
ReloadableType rtype = r.addType(t, loadBytesForClass(t));
result = runUnguarded(rtype.getClazz(), "run");
assertEquals("hello", result.returnValue);
captureOn();
rtype.loadNewVersion("4", retrieveRename(t, t + "4"));
output = captureOff();
assertContains("ReloadEventProcessorPlugin1: unableToReloadEvent(simple.Basic,simple.Basic,4)", output);
result = runUnguarded(rtype.getClazz(), "run");
assertEquals("hello", result.returnValue);
}
@SuppressWarnings("unused")
@Test
public void testServicesFileWithPluginCommentedOut() throws Exception {
binLoader = new TestClassloaderWithRewriting("meta2", true);
String t = "simple.Basic";
captureOn();
TypeRegistry r = getTypeRegistry(t);
String output = captureOff();
assertDoesNotContain("Instantiated ReloadEventProcessorPlugin1", output);
}
@SuppressWarnings("unused")
@Test
public void testServicesFileWithPluginAndNoNewline() throws Exception {
binLoader = new TestClassloaderWithRewriting("meta3", true);
String t = "simple.Basic";
captureOn();
TypeRegistry r = getTypeRegistry(t);
String output = captureOff();
assertContains("Instantiated ReloadEventProcessorPlugin1", output);
}
// registering a global plugin
@Test
public void testGlobalPluginRegistration() throws Exception {
binLoader = new TestClassloaderWithRewriting("metaNotExist", true);
String t = "simple.Basic";
ReloadEventProcessorPlugin repp = new ReloadEventProcessorPlugin() {
public void reloadEvent(String typename, Class<?> clazz, String encodedTimestamp) {
System.out.println("Plugin: reloadEvent(" + typename + "," + clazz.getName() + "," + encodedTimestamp + ")");
}
public boolean shouldRerunStaticInitializer(String typename, Class<?> clazz, String encodedTimestamp) {
return false;
}
};
try {
Plugins.registerGlobalPlugin(repp);
TypeRegistry r = getTypeRegistry(t);
ReloadableType rtype = r.addType(t, loadBytesForClass(t));
captureOn();
rtype.loadNewVersion("2", retrieveRename(t, t + "2"));
String output = captureOff();
System.out.println(output);
assertContains("Reloading: Loading new version of simple.Basic [2]", output);
assertUniqueContains("Plugin: reloadEvent(simple.Basic,simple.Basic,2)", output);
result = runUnguarded(rtype.getClazz(), "run");
assertEquals("goodbye", result.returnValue);
} finally {
Plugins.unregisterGlobalPlugin(repp);
}
}
@Test
public void testPluginRerunStaticInitializerRequest() throws Exception {
binLoader = new TestClassloaderWithRewriting("metaNotExist", true);
String t = "simple.Basic";
ReloadEventProcessorPlugin repp = new ReloadEventProcessorPlugin() {
public void reloadEvent(String typename, Class<?> clazz, String encodedTimestamp) {
System.out.println("Plugin: reloadEvent(" + typename + "," + clazz.getName() + "," + encodedTimestamp + ")");
}
public boolean shouldRerunStaticInitializer(String typename, Class<?> clazz, String encodedTimestamp) {
System.out.println("Plugin: rerun request for " + typename);
return false;
}
};
try {
Plugins.registerGlobalPlugin(repp);
TypeRegistry r = getTypeRegistry(t);
ReloadableType rtype = r.addType(t, loadBytesForClass(t));
captureOn();
rtype.loadNewVersion("2", retrieveRename(t, t + "2"));
String output = captureOff();
System.out.println(output);
assertContains("Reloading: Loading new version of simple.Basic [2]", output);
assertUniqueContains("Plugin: reloadEvent(simple.Basic,simple.Basic,2)", output);
assertContains("Reloading: Loading new version of simple.Basic [2]", output);
assertUniqueContains("Plugin: rerun request for simple.Basic", output);
result = runUnguarded(rtype.getClazz(), "run");
assertEquals("goodbye", result.returnValue);
} finally {
Plugins.unregisterGlobalPlugin(repp);
}
}
@Test
public void testPluginRerunStaticInitializerRequest2() throws Exception {
binLoader = new TestClassloaderWithRewriting("metaNotExist", true);
String t = "clinit.One";
ReloadEventProcessorPlugin repp = new ReloadEventProcessorPlugin() {
public void reloadEvent(String typename, Class<?> clazz, String encodedTimestamp) {
System.out.println("Plugin: reloadEvent(" + typename + "," + clazz.getName() + "," + encodedTimestamp + ")");
}
public boolean shouldRerunStaticInitializer(String typename, Class<?> clazz, String encodedTimestamp) {
System.out.println("Plugin: rerun request for " + typename);
return true; // if this were false, the result below would be 5!
}
};
try {
Plugins.registerGlobalPlugin(repp);
TypeRegistry r = getTypeRegistry(t);
ReloadableType rtype = r.addType(t, loadBytesForClass(t));
captureOn();
rtype.loadNewVersion("2", retrieveRename(t, t + "2"));
String output = captureOff();
System.out.println(output);
assertContains("Reloading: Loading new version of clinit.One [2]", output);
assertUniqueContains("Plugin: reloadEvent(clinit.One,clinit.One,2)", output);
assertContains("Reloading: Loading new version of clinit.One [2]", output);
assertUniqueContains("Plugin: rerun request for clinit.One", output);
result = runUnguarded(rtype.getClazz(), "run");
assertEquals("7", result.returnValue);
} finally {
Plugins.unregisterGlobalPlugin(repp);
}
}
}