Search in sources :

Example 91 with Result

use of org.springsource.loaded.test.infra.Result in project spring-loaded by spring-projects.

the class MethodInvokerRewriterTests method rewriteInvokeStatic5.

/**
	 * Reloading target where the method to call has been deleted.
	 * <p>
	 * Here is what happens in the Java case (class A calling static method B.foo that has been deleted):
	 * 
	 * <pre>
	 * Exception in thread "main" java.lang.NoSuchMethodError: B.foo()V
	 *   at A.main(A.java:3)
	 * </pre>
	 */
@Test
public void rewriteInvokeStatic5() throws Exception {
    TypeRegistry typeRegistry = getTypeRegistry("tgt.SimpleClass");
    ReloadableType callee = typeRegistry.addType("tgt.SimpleClass", loadBytesForClass("tgt.SimpleClass"));
    byte[] callerbytes = loadBytesForClass("tgt.StaticCaller");
    byte[] rewrittenBytes = MethodInvokerRewriter.rewrite(typeRegistry, callerbytes);
    Class<?> callerClazz = loadit("tgt.StaticCaller", rewrittenBytes);
    // run the original
    Result result = runUnguarded(callerClazz, "run");
    assertEquals(123, result.returnValue);
    // new version of SimpleClass where target static method has been removed
    callee.loadNewVersion("5", retrieveRename("tgt.SimpleClass", "tgt.SimpleClass005"));
    try {
        result = runUnguarded(callerClazz, "run");
        Assert.fail();
    } catch (InvocationTargetException ite) {
        Throwable t = ite.getCause();
        NoSuchMethodError icce = (NoSuchMethodError) t;
        assertEquals("SimpleClass.toInt(Ljava/lang/String;)I", icce.getMessage());
    }
}
Also used : ReloadableType(org.springsource.loaded.ReloadableType) TypeRegistry(org.springsource.loaded.TypeRegistry) InvocationTargetException(java.lang.reflect.InvocationTargetException) Result(org.springsource.loaded.test.infra.Result) Test(org.junit.Test)

Example 92 with Result

use of org.springsource.loaded.test.infra.Result in project spring-loaded by spring-projects.

the class MethodInvokerRewriterTests method rewriteInvokeStatic2.

//	@Test
//	public void rewriteMethodAccessesGetIntNonStatic() throws Exception {
//		TypeRegistry typeRegistry = TypeRegistry.getTypeRegistryFor(binLoader);
//		configureForTesting(typeRegistry, "data.Apple");
//
//		byte[] caller = retrieveBytesForClass("data.Orange");
//		checkMethod(caller, "accessFieldOnApple",
//				" L0\n" +
//				"    ALOAD 0\n" +
//				"    GETFIELD data/Orange.appleLdata/Apple;\n" +
//				"    GETFIELD data/Apple.intFieldI\n" +
//				"    ISTORE 1\n" +
//				" L1\n" +
//				"    ILOAD 1\n" +
//				"    IRETURN\n" +
//				" L2\n");
//
//		byte[] rewrittenBytes = MethodCallAndFieldAccessRewriter.rewrite(typeRegistry, caller);
//		checkMethod(rewrittenBytes, "accessFieldOnApple",
//				" L0\n" +
//				"    ALOAD 0\n" +
//				"    GETFIELD data/Orange.appleLdata/Apple;\n" +
//				"    LDC intField\n" +
//				"    LDC I\n" +
//				"    INVOKEVIRTUAL data/Apple.r$get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;\n" +
//				"    CHECKCAST java/lang/Integer\n" +
//				"    INVOKEVIRTUAL java/lang/Integer.intValue()I\n" +
//				"    ISTORE 1\n" +
//				" L1\n" +
//				"    ILOAD 1\n" +
//				"    IRETURN\n" +
//				" L2\n");
//
//	}
//
//	@Test
//	public void rewriteMethodAccessesGetIntStatic() throws Exception {
//		TypeRegistry typeRegistry = TypeRegistry.getTypeRegistryFor(binLoader);
//		// Configure it directly such that data.Apple is considered reloadable
//		configureForTesting(typeRegistry, "data.Apple");
//		typeRegistry.addType("data.Apple", retrieveBytesForClass("data.Apple"));
//
//		byte[] caller = retrieveBytesForClass("data.Orange");
//		checkMethod(caller, "getStaticFieldOnApple",
//				" L0\n" +
//				"    GETSTATIC data/Apple.staticIntFieldI\n" +
//				"    IRETURN\n" +
//				" L1\n");
//
//		byte[] rewrittenBytes = MethodCallAndFieldAccessRewriter.rewrite(typeRegistry, caller);
//		checkMethod(rewrittenBytes, "getStaticFieldOnApple",
//				" L0\n" +
//				"    LDC staticIntField\n" +
//				"    LDC I\n" +
//				"    INVOKESTATIC data/Apple.r$gets(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;\n" +
//				"    CHECKCAST java/lang/Integer\n" +
//				"    INVOKEVIRTUAL java/lang/Integer.intValue()I\n" +
//				"    IRETURN\n" +
//				" L1\n");
//
//		Class<?> callerClass = loadit("data.Orange", rewrittenBytes);
//		Object o = callerClass.newInstance();
//		runOnInstance(callerClass, o, "setStaticFieldOnApple");
//		Result result = runOnInstance(callerClass, o, "getStaticFieldOnApple");
//		assertEquals(35, result.returnValue);
//
//		// calling it again on a different instance (static so should give same result)
//		result = runOnInstance(callerClass, callerClass.newInstance(), "getStaticFieldOnApple");
//		assertEquals(35, result.returnValue);
//	}
//
//	@Test
//	public void rewriteMethodAccessesSetIntNonStatic() throws Exception {
//		TypeRegistry typeRegistry = TypeRegistry.getTypeRegistryFor(binLoader);
//		// Configure it directly such that data.Apple is considered reloadable
//		configureForTesting(typeRegistry, "data.Apple");
//		typeRegistry.addType("data.Apple", retrieveBytesForClass("data.Apple"));
//
//		byte[] caller = retrieveBytesForClass("data.Orange");
//		checkMethod(caller, "setFieldOnApple",
//				" L0\n" +
//				"    ALOAD 0\n" +
//				"    GETFIELD data/Orange.appleLdata/Apple;\n" +
//				"    BIPUSH 35\n" +
//				"    PUTFIELD data/Apple.intFieldI\n" +
//				" L1\n" +
//				"    RETURN\n" +
//				" L2\n");
//
//		byte[] rewrittenBytes = MethodCallAndFieldAccessRewriter.rewrite(typeRegistry, caller);
//		checkMethod(rewrittenBytes, "setFieldOnApple",
//				" L0\n" +
//				"    ALOAD 0\n" +
//				"    GETFIELD data/Orange.appleLdata/Apple;\n" +
//				"    BIPUSH 35\n" +
//				"    INVOKESTATIC java/lang/Integer.valueOf(I)Ljava/lang/Integer;\n" +
//				"    LDC intField\n" +
//				"    LDC I\n" +
//				"    INVOKEVIRTUAL data/Apple.r$set(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V\n" +
//				" L1\n" +
//				"    RETURN\n" +
//				" L2\n");
//
//		checkMethod(caller, "accessFieldOnApple",
//				" L0\n" +
//				"    ALOAD 0\n" +
//				"    GETFIELD data/Orange.appleLdata/Apple;\n" +
//				"    GETFIELD data/Apple.intFieldI\n" +
//				"    ISTORE 1\n" +
//				" L1\n" +
//				"    ILOAD 1\n" +
//				"    IRETURN\n" +
//				" L2\n");
//
//		checkMethod(rewrittenBytes, "accessFieldOnApple",
//				" L0\n" +
//				"    ALOAD 0\n" +
//				"    GETFIELD data/Orange.appleLdata/Apple;\n" +
//				"    LDC intField\n" +
//				"    LDC I\n" +
//				"    INVOKEVIRTUAL data/Apple.r$get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;\n" +
//				"    CHECKCAST java/lang/Integer\n" +
//				"    INVOKEVIRTUAL java/lang/Integer.intValue()I\n" +
//				"    ISTORE 1\n" +
//				" L1\n" +
//				"    ILOAD 1\n" +
//				"    IRETURN\n" +
//				" L2\n");
//
//		Class<?> callerClass = loadit("data.Orange", rewrittenBytes);
//		Object o = callerClass.newInstance();
//		runOnInstance(callerClass, o, "setFieldOnApple");
//		Result result = runOnInstance(callerClass, o, "accessFieldOnApple");
//		assertEquals(35, result.returnValue);
//
//		// and again on a different instance - should not be set this time
//		result = runOnInstance(callerClass, callerClass.newInstance(), "accessFieldOnApple");
//		assertEquals(0, result.returnValue);
//	}
// change GETFIELD <RELOADABLETYPE>.name<TYPE>
// Change it to use a field accessor
// we need to allow for calls to a field that gets removed
// and to a field that is being added
// Apple.s$get("intField","I") (will return a boxed Integer)
// (with an unbox on the client side - as the requested type is int)
// TODO review optimization of having static 'pack' methods with a variety of input params, returning an Object[] - will save a bunch of instructions
// TODO review optimization of calling to a generated method (synthetic) that can do the packing (so synthetic has same params/return as invokestatic site)
// this second optimization would greatly reduce generated code
// TODO review optimization: extending 2 could even pull the invokestatic of anyChanges out into that helper too
/**
	 * Rewrite of a simple INVOKESTATIC call - change the callee (to exercise the dispatching through the interface).
	 * This checks the behaviour of the TypeRegistry.anyChanges(int, String) method which determines whether we have to
	 * dispatch to something different due to a reload.
	 */
@Test
public void rewriteInvokeStatic2() throws Exception {
    TypeRegistry typeRegistry = getTypeRegistry("tgt.SimpleClass");
    ReloadableType callee = typeRegistry.addType("tgt.SimpleClass", loadBytesForClass("tgt.SimpleClass"));
    byte[] callerbytes = loadBytesForClass("tgt.StaticCaller");
    byte[] rewrittenBytes = MethodInvokerRewriter.rewrite(typeRegistry, callerbytes);
    Class<?> callerClazz = loadit("tgt.StaticCaller", rewrittenBytes);
    //		ClassPrinter.print(callee.bytesLoaded);
    // run the original
    Result result = runUnguarded(callerClazz, "run");
    assertEquals(123, result.returnValue);
    callerbytes = loadBytesForClass("tgt.StaticCaller002");
    callerbytes = ClassRenamer.rename("tgt.StaticCaller002", callerbytes, "tgt.SimpleClass002:tgt.SimpleClass");
    rewrittenBytes = MethodInvokerRewriter.rewrite(typeRegistry, callerbytes);
    Class<?> callerClazz002 = loadit("tgt.StaticCaller002", rewrittenBytes);
    callee.loadNewVersion("2", retrieveRename("tgt.SimpleClass", "tgt.SimpleClass002"));
    result = runUnguarded(callerClazz002, "run2");
    assertEquals("456", result.returnValue);
}
Also used : ReloadableType(org.springsource.loaded.ReloadableType) TypeRegistry(org.springsource.loaded.TypeRegistry) Result(org.springsource.loaded.test.infra.Result) Test(org.junit.Test)

Example 93 with Result

use of org.springsource.loaded.test.infra.Result in project spring-loaded by spring-projects.

the class MethodInvokerRewriterTests method callingMethodIntroducedLaterReturningPrimitiveChar.

@Test
public void callingMethodIntroducedLaterReturningPrimitiveChar() throws Exception {
    TypeRegistry typeRegistry = TypeRegistry.getTypeRegistryFor(binLoader);
    // Configure it directly such that data.Apple is considered reloadable
    configureForTesting(typeRegistry, "data.Apple");
    ReloadableType apple = typeRegistry.addType("data.Apple", loadBytesForClass("data.Apple"));
    byte[] callerbytes = loadBytesForClass("data.Orange002");
    callerbytes = ClassRenamer.rename("data.Orange", callerbytes, "data.Apple002:data.Apple");
    byte[] rewrittenBytes = MethodInvokerRewriter.rewrite(typeRegistry, callerbytes);
    Class<?> callerClazz = loadit("data.Orange", rewrittenBytes);
    runExpectNoSuchMethodException(callerClazz, "callAppleRetChar", new Object[] { (char) 'a' });
    // Load a version of Apple that does define that method
    apple.loadNewVersion("002", retrieveRename("data.Apple", "data.Apple002"));
    Result result = runUnguarded(callerClazz, "callAppleRetChar", new Object[] { (char) 'a' });
    assertEquals('b', result.returnValue);
}
Also used : ReloadableType(org.springsource.loaded.ReloadableType) TypeRegistry(org.springsource.loaded.TypeRegistry) Result(org.springsource.loaded.test.infra.Result) Test(org.junit.Test)

Example 94 with Result

use of org.springsource.loaded.test.infra.Result in project spring-loaded by spring-projects.

the class MethodInvokerRewriterTests method rewriteInvokeStatic4.

/**
	 * Reloading target with a modified static method.
	 */
@Test
public void rewriteInvokeStatic4() throws Exception {
    TypeRegistry typeRegistry = getTypeRegistry("tgt.SimpleClass");
    ReloadableType callee = typeRegistry.addType("tgt.SimpleClass", loadBytesForClass("tgt.SimpleClass"));
    byte[] callerbytes = loadBytesForClass("tgt.StaticCaller");
    byte[] rewrittenBytes = MethodInvokerRewriter.rewrite(typeRegistry, callerbytes);
    Class<?> callerClazz = loadit("tgt.StaticCaller", rewrittenBytes);
    // run the original
    Result result = runUnguarded(callerClazz, "run");
    assertEquals(123, result.returnValue);
    // new version of SimpleClass always returns 256
    callee.loadNewVersion("4", retrieveRename("tgt.SimpleClass", "tgt.SimpleClass004"));
    result = runUnguarded(callerClazz, "run");
    assertEquals(256, result.returnValue);
}
Also used : ReloadableType(org.springsource.loaded.ReloadableType) TypeRegistry(org.springsource.loaded.TypeRegistry) Result(org.springsource.loaded.test.infra.Result) Test(org.junit.Test)

Example 95 with Result

use of org.springsource.loaded.test.infra.Result in project spring-loaded by spring-projects.

the class SpringLoadedTests method runConstructor.

public Result runConstructor(Class<?> clazz, String paramDescriptor, Object... params) throws InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
    PrintStream oldo = System.out;
    PrintStream olde = System.err;
    Object result = null;
    ByteArrayOutputStream oso = new ByteArrayOutputStream();
    ByteArrayOutputStream ose = new ByteArrayOutputStream();
    try {
        if (capture) {
            System.setOut(new PrintStream(oso));
            System.setErr(new PrintStream(ose));
        }
        Constructor<?>[] cs = clazz.getConstructors();
        Constructor<?> c = null;
        for (Constructor<?> ctor : cs) {
            Class<?>[] paramClazzes = ctor.getParameterTypes();
            String toParamDescriptorString = toParamDescriptorString(paramClazzes);
            //				System.out.println(toParamDescriptorString + "<<");
            if (paramDescriptor.equals(toParamDescriptorString)) {
                c = ctor;
                break;
            }
        }
        if (c == null) {
            Assert.fail("Invocation failure: could not find constructor with param descriptor " + paramDescriptor + " on type '" + clazz.getName());
        }
        c.setAccessible(true);
        result = c.newInstance(params);
    } finally {
        if (capture) {
            System.setOut(oldo);
            System.setErr(olde);
        }
    }
    return new Result(result, oso.toString().replace("\r", ""), ose.toString().replace("\r", ""));
}
Also used : PrintStream(java.io.PrintStream) Constructor(java.lang.reflect.Constructor) ByteArrayOutputStream(java.io.ByteArrayOutputStream) Result(org.springsource.loaded.test.infra.Result)

Aggregations

Result (org.springsource.loaded.test.infra.Result)155 Test (org.junit.Test)139 ReloadableType (org.springsource.loaded.ReloadableType)106 TypeRegistry (org.springsource.loaded.TypeRegistry)97 ResultException (org.springsource.loaded.test.infra.ResultException)28 Method (java.lang.reflect.Method)27 InvocationTargetException (java.lang.reflect.InvocationTargetException)7 ByteArrayOutputStream (java.io.ByteArrayOutputStream)5 PrintStream (java.io.PrintStream)5 Constructor (java.lang.reflect.Constructor)4 Ignore (org.junit.Ignore)4 Field (java.lang.reflect.Field)2 ReflectiveInterceptor.jlClassGetField (org.springsource.loaded.ri.ReflectiveInterceptor.jlClassGetField)1