Package org.springsource.loaded.test

Source Code of org.springsource.loaded.test.SpringLoadedTests

/*
* 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.fail;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.LocalVariableNode;
import org.objectweb.asm.tree.MethodNode;
import org.springsource.loaded.ClassRenamer;
import org.springsource.loaded.Constants;
import org.springsource.loaded.ISMgr;
import org.springsource.loaded.MethodMember;
import org.springsource.loaded.NameRegistry;
import org.springsource.loaded.ReloadableType;
import org.springsource.loaded.SSMgr;
import org.springsource.loaded.TypeDescriptor;
import org.springsource.loaded.TypeRegistry;
import org.springsource.loaded.Utils;
import org.springsource.loaded.agent.SpringLoadedPreProcessor;
import org.springsource.loaded.test.ReloadingJVM.JVMOutput;
import org.springsource.loaded.test.infra.ClassPrinter;
import org.springsource.loaded.test.infra.MethodPrinter;
import org.springsource.loaded.test.infra.Result;
import org.springsource.loaded.test.infra.ResultException;
import org.springsource.loaded.test.infra.TestClassLoader;


/**
* Abstract root test class containing helper functions.
*
* @author Andy Clement
* @since 1.0
*/
public abstract class SpringLoadedTests implements Constants {

  /**
   * Classloader that can be used to see things in the bin directory, it is initialised ready for each test to use.
   */
  protected ClassLoader binLoader;

  protected String TestDataPath = TestUtils.getPathToClasses("../testdata");
  protected String TestDataAspectJPath = TestUtils.getPathToClasses("../testdata-aspectj");
  protected String GroovyTestDataPath = TestUtils.getPathToClasses("../testdata-groovy");
  protected String AspectjrtJar = "../testdata/aspectjrt.jar";
  protected String CodeJar = "../testdata/code.jar";
  // TODO [java8] replace this with project dependency when Java8 is out
  protected String Java8CodeJar = findJar("../testdata-java8/build/libs","testdata-java8");
  protected String GroovyrtJar = "../testdata-groovy/groovy-all-1.8.6.jar";
  protected Result result;
  protected TypeRegistry registry;

 
  @Before
  public void setup() throws Exception {
    SpringLoadedPreProcessor.disabled = true;
    NameRegistry.reset();
    binLoader = new TestClassLoader(toURLs(TestDataPath, TestDataAspectJPath, AspectjrtJar, CodeJar, Java8CodeJar), this.getClass().getClassLoader());
  }

  @After
  public void teardown() throws Exception {
    SpringLoadedPreProcessor.disabled = false;
  }

  public void switchToGroovy() {
    binLoader = new TestClassLoader(toURLs(GroovyTestDataPath, GroovyrtJar), this.getClass().getClassLoader());
    //    Thread.currentThread().setContextClassLoader(binLoader);
  }

  /**
   * Convert an array of string paths to an array of URLs
   *
   * @param paths the string paths
   * @return the converted URLs
   */
  public URL[] toURLs(String... paths) {
    URL[] urls = new URL[paths.length];
    int i = 0;
    for (String path : paths) {
      try {
        urls[i++] = new File(path).toURI().toURL();
      } catch (MalformedURLException e) {
        Assert.fail(e.toString());
      }
    }
    return urls;
  }

  public Object run(Class<?> clazz, String methodname, Object... params) {
    try {
      //      System.out.println("Calling method " + methodname + " on " + clazz.getName());
      Object o = clazz.newInstance();
      Method m = null;
      Method[] ms = clazz.getMethods();
      for (Method mm : ms) {
        if (mm.getName().equals(methodname)) {
          m = mm;
          break;
        }
      }
      // Method m = clazz.getDeclaredMethod(methodname);
      return m.invoke(o, params);
    } catch (Exception e) {
      e.printStackTrace();
      Assert.fail(e.toString());
      return null;
    }
  }

  public Object run(Class<?> clazz, Object o, String methodname, Object... params) {
    try {
      System.out.println("Calling method " + methodname + " on " + clazz.getName());
      Method m = null;
      Method[] ms = clazz.getMethods();
      for (Method mm : ms) {
        if (mm.getName().equals(methodname)) {
          m = mm;
          break;
        }
      }
      // Method m = clazz.getDeclaredMethod(methodname);
      return m.invoke(o, params);
    } catch (Exception e) {
      e.printStackTrace();
      Assert.fail(e.toString());
      return null;
    }
  }

  public static boolean capture = true;

  public Result runUnguardedWithCCL(Class<?> clazz, ClassLoader ccl, String methodname, Object... params)
      throws InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException,
      IllegalArgumentException, InvocationTargetException {
    ClassLoader oldCCL = Thread.currentThread().getContextClassLoader();
    try {
      Thread.currentThread().setContextClassLoader(ccl);
      return runUnguarded(clazz, methodname, params);
    } finally {
      Thread.currentThread().setContextClassLoader(oldCCL);
    }
  }

  public Result runUnguarded(Class<?> clazz, String methodname, 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));
      }

      Object o = clazz.newInstance();
      Method m = null;
      Method[] ms = clazz.getMethods();
      for (Method mm : ms) {
        if (mm.getName().equals(methodname)) {
          m = mm;
          break;
        }
      }
      if (m == null) {
        Assert.fail("Invocation failure: could not find method '" + methodname + "' on type '" + clazz.getName());
      }
      m.setAccessible(true);
      result = m.invoke(o, params);
    } finally {
      if (capture) {
        System.setOut(oldo);
        System.setErr(olde);
      }
    }
    return new Result(result, oso.toString().replace("\r", ""), ose.toString().replace("\r", ""));
  }

  public Result runStaticUnguarded(Class<?> clazz, String methodname, 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));
      }

      Method m = null;
      Method[] ms = clazz.getMethods();
      for (Method mm : ms) {
        if (mm.getName().equals(methodname)) {
          m = mm;
          break;
        }
      }
      if (m == null) {
        Assert.fail("Invocation failure: could not find method '" + methodname + "' on type '" + clazz.getName());
      }
      m.setAccessible(true);
      result = m.invoke(null, params);
    } finally {
      if (capture) {
        System.setOut(oldo);
        System.setErr(olde);
      }
    }
    return new Result(result, oso.toString().replace("\r", ""), ose.toString().replace("\r", ""));
  }

  public Result runConstructor(Class<?> clazz, int whichConstructor, 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();
    Constructor<?> c = null;
    try {
      if (capture) {
        System.setOut(new PrintStream(oso));
        System.setErr(new PrintStream(ose));
      }

      Constructor<?>[] cs = clazz.getConstructors();
      c = cs[whichConstructor];
      System.out.println(c);
      if (c == null) {
        Assert.fail("Invocation failure: could not find constructor " + whichConstructor + " 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", ""));
  }

  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", ""));
  }

  private String toParamDescriptorString(Class<?>[] paramClazzes) {
    if (paramClazzes == null) {
      return "";
    }
    StringBuilder s = new StringBuilder();
    for (Class<?> c : paramClazzes) {
      s.append(c.getName());
      s.append(" ");
    }
    return s.toString().trim();
  }

  public void runExpectNoSuchMethodException(Class<?> clazz, String methodname, Object... params) throws InstantiationException,
      IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
    try {
      runUnguarded(clazz, methodname, params);
      Assert.fail("should not work, NSME should occur for " + methodname);
    } catch (InvocationTargetException ite) {
      String cause = ite.getCause().toString();
      if (!cause.startsWith("java.lang.NoSuchMethodError")) {
        ite.printStackTrace();
        Assert.fail("Should be a NoSuchMethodError, but got " + ite);
      }
    }
  }

  public static boolean printOutput = false;

  /**
   * Proposed alternate version of runOnInstance that produces a wrapper Exception object similar to the Result object, but where
   * the "result" is an exception. This is done so as not to lose the grabbed output when exception is raised by the test case.
   */
  public static Result runOnInstance(Class<?> clazz, Object instance, String methodname, Object... params) throws ResultException {

    PrintStream oldo = System.out;
    PrintStream olde = System.err;
    Object result = null;
    Throwable exception = null;
    ByteArrayOutputStream oso = new ByteArrayOutputStream();
    ByteArrayOutputStream ose = new ByteArrayOutputStream();
    try {
      if (capture) {
        System.setOut(new PrintStream(oso));
        System.setErr(new PrintStream(ose));
      }

      Method m = null;
      Method[] ms = clazz.getMethods();
      for (Method mm : ms) {
        if (mm.getName().equals(methodname)) {
          m = mm;
          break;
        }
      }
      if (m == null) {
        throw new IllegalStateException("No method called " + methodname + " to call on type "
            + (instance == null ? "null" : instance.getClass().getName()));
      }
      try {
        result = m.invoke(instance, params);
      } catch (Throwable e) {
        exception = e;
      }

    } finally {
      System.setOut(oldo);
      System.setErr(olde);
    }
    if (printOutput) {
      System.out.println("Collected output running: " + methodname);
      System.out.println(oso.toString());
      System.out.println(ose.toString());
    }
    if (exception != null) {
      throw new ResultException(exception, oso.toString().replace("\r", ""), ose.toString().replace("\r", ""));
    } else {
      return new Result(result, oso.toString().replace("\r", ""), ose.toString().replace("\r", ""));
    }
  }

  // attempt definition - kind of a lightweight way to see if it is OK
  public Class<?> loadit(String name, byte[] bytes) {
    try {
      return ((TestClassLoader) binLoader).defineTheClass(name, bytes);
    } catch (RuntimeException t) {
      ClassPrinter.print(bytes);
      t.printStackTrace();
      throw t;
    }
  }

  public Class<?> loadClass(String name) {
    return loadit(name, loadBytesForClass(name));
  }

  protected byte[] retrieveRename(String newName, String name) {
    return ClassRenamer.rename(newName, loadBytesForClass(name));
  }

  /**
   * retargets are "from.this.thing:to.this.thing"
   *
   * @param newName
   * @param name
   * @param retargets of the form "this.from:this.to"
   * @return
   */
  protected byte[] retrieveRename(String newName, String name, String... retargets) {
    return ClassRenamer.rename(newName, loadBytesForClass(name), retargets);
  }

  protected byte[] loadBytesForClass(String dottedClassName) {
    byte[] data = Utils.loadDottedClassAsBytes(binLoader, dottedClassName);
    Assert.assertNotNull(data);
    Assert.assertNotSame(0, data.length);
    return data;
  }

  protected String getStamp(String classname) {
    return getStamp(binLoader, classname);
  }

  public static byte[] retrieveClass(ClassLoader loader, String classname) {
    byte[] data = Utils.loadDottedClassAsBytes(loader, classname);
    Assert.assertNotNull(data);
    Assert.assertNotSame(0, data.length);
    return data;
  }

  protected void print(byte[] classdata) {
    ClassReader reader = new ClassReader(classdata);
    reader.accept(new ClassPrinter(System.out), 0);
  }

  protected String printItAndReturnIt(byte[] classdata) {
    return printItAndReturnIt(classdata, false);
  }

  protected String printItAndReturnIt(byte[] classdata, boolean quoted) {
    OutputStream os = new SimpleOutputStream();
    ClassReader reader = new ClassReader(classdata);
    reader.accept(new ClassPrinter(new PrintStream(os)), 0);
    StringBuffer sb = new StringBuffer(os.toString().replace("\r", ""));
    if (!quoted) {
      return sb.toString();
    }
    for (int i = 0; i < sb.length(); i++) {
      if (sb.charAt(i) == '\n') {
        sb.insert(i + 1, "\"");
        sb.insert(i, "\\n\"+");
        i += 4;
      }
    }
    sb.delete(sb.length() - 3, sb.length());
    sb.insert(0, "\"");
    return sb.toString();
  }

  @SuppressWarnings("unchecked")
  private MethodNode getMethod(byte[] classbytes, String methodName) {
    ClassReader super_cr = new ClassReader(classbytes);
    ClassNode cn = new ClassNode();
    super_cr.accept(cn, 0);
    List<MethodNode> methods = cn.methods;
    if (methods != null) {
      for (MethodNode mn : methods) {
        if (mn.name.equals(methodName)) {
          return mn;
        }
      }
    }
    return null;
  }

  @SuppressWarnings("unchecked")
  private FieldNode getField(byte[] classbytes, String fieldName) {
    ClassReader super_cr = new ClassReader(classbytes);
    ClassNode cn = new ClassNode();
    super_cr.accept(cn, 0);
    List<FieldNode> fields = cn.fields;
    if (fields != null) {
      for (FieldNode fn : fields) {
        if (fn.name.equals(fieldName)) {
          return fn;
        }
      }
    }
    return null;
  }

  protected ClassNode getClassNode(byte[] classdata) {
    ClassNode cn = new ClassNode();
    ClassReader cr = new ClassReader(classdata);
    cr.accept(cn, 0)
    return cn;
  }

  @SuppressWarnings("unchecked")
  protected List<MethodNode> getMethods(byte[] classdata) {
    return getClassNode(classdata).methods;
  }
 
  protected int countMethods(byte[] classdata) {
    ClassNode cn = getClassNode(classdata);
    return cn.methods==null?0:cn.methods.size();
 

  protected List<MethodNode> filter(List<MethodNode> methods, String nameSubstring) {
    if (methods == null) { return Collections.<MethodNode>emptyList(); }
    List<MethodNode> subset = new ArrayList<MethodNode>();
    for (MethodNode methodNode: methods) {
      if (methodNode.name.contains(nameSubstring)) {
        subset.add(methodNode);
      }
    }
    return subset;
  }
 
  protected String toStringClass(byte[] classdata) {
    return toStringClass(classdata, false, false);
  }

  protected String toStringClass(byte[] classdata, boolean includeBytecode) {
    return toStringClass(classdata, includeBytecode, false);
  }

  protected String toStringClass(byte[] classdata, boolean includeBytecode, boolean quoted) {
    OutputStream os = new SimpleOutputStream();
    ClassPrinter.print(new PrintStream(os), classdata, includeBytecode);
    String s = os.toString();
    StringBuffer sb = new StringBuffer(s.replaceAll("\r", ""));
    if (!quoted) {
      return sb.toString();
    }
    for (int i = 0; i < sb.length(); i++) {
      if (sb.charAt(i) == '\n') {
        sb.insert(i + 1, "\"");
        sb.insert(i, "\\n\"+");
        i += 4;
      }
    }
    sb.insert(0, "\"");
    sb.delete(sb.length() - 3, sb.length());
    return sb.toString();
  }

  protected String toStringMethod(byte[] classdata, String methodname, boolean quoted) {
    OutputStream os = new SimpleOutputStream();
    // ClassReader reader = new ClassReader(classdata);
    MethodNode one = getMethod(classdata, methodname);
    one.instructions.accept(new MethodPrinter(new PrintStream(os)));
    String s = os.toString();
    StringBuffer sb = new StringBuffer(s.replaceAll("\r", ""));
    if (!quoted) {
      return sb.toString();
    }
    for (int i = 0; i < sb.length(); i++) {
      if (sb.charAt(i) == '\n') {
        sb.insert(i + 1, "\"");
        sb.insert(i, "\\n\"+");
        i += 4;
      }
    }
    sb.insert(0, "Method is " + methodname + "\n\"");
    sb.delete(sb.length() - 3, sb.length());
    return sb.toString();
  }

  public static String findJar(String whereToLook, String jarPrefix) {
    File dir = new File(whereToLook);
    File[] fs = dir.listFiles();
    for (File f: fs) {
      if (f.getName().startsWith(jarPrefix)) {
        return f.toString();
      }
    }
    return null;
  }
 
  @SuppressWarnings("unchecked")
  protected String toStringField(byte[] classdata, String fieldname) {
    StringBuilder sb = new StringBuilder();
    FieldNode fieldNode = getField(classdata, fieldname);
    if (fieldNode == null) {
      return null;
    }
    List<AnnotationNode> annos = fieldNode.visibleAnnotations;
    if (annos != null) {
      sb.append("vis(").append(toStringAnnotations(annos)).append(") ");
    }
    annos = fieldNode.invisibleAnnotations;
    if (annos != null) {
      sb.append("invis(").append(toStringAnnotations(annos)).append(") ");
    }
    // will need implementing at some point:
    //    List<Attribute> attrs = fieldNode.attrs;
    //    if (attrs = !null) {
    //      sb.append("attrs(").append(toStringAttributes(attrs)).append(") ");
    //    }
    sb.append("0x").append(Integer.toHexString(fieldNode.access)).append("(")
        .append(ClassPrinter.toAccessForMember(fieldNode.access)).append(") ");
    sb.append(fieldNode.name).append(" ");
    sb.append(fieldNode.desc).append(" ");
    if (fieldNode.signature != null) {
      sb.append(fieldNode.signature).append(" ");
    }
    if (fieldNode.value != null) {
      sb.append(fieldNode.value).append(" ");
    }
    return sb.toString().trim();
  }

  private String toStringAnnotations(List<AnnotationNode> annos) {
    StringBuilder sb = new StringBuilder();
    for (AnnotationNode anno : annos) {
      sb.append(toStringAnnotation(anno)).append(" ");
    }
    return sb.toString().trim();
  }

  private String toStringAnnotation(AnnotationNode anno) {
    StringBuilder sb = new StringBuilder();
    sb.append(anno.desc);
    if (anno.values != null) {
      for (int i = 0; i < anno.values.size(); i = i + 2) {
        if (i > 0) {
          sb.append(" ");
        }
        sb.append(toStringAnnotationValue((String) anno.values.get(i), anno.values.get(i + 1)));
      }
    }

    return sb.toString().trim();
  }

  /**
   * From asm:
   *
   * The name value pairs of this annotation. Each name value pair is stored as two consecutive elements in the list. The name is
   * a {@link String}, and the value may be a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short}, {@link Integer},
   * {@link Long}, {@link Float}, {@link Double}, {@link String} or {@link org.objectweb.asm.Type}, or an two elements String
   * array (for enumeration values), a {@link AnnotationNode}, or a {@link List} of values of one of the preceding types. The list
   * may be <tt>null</tt> if there is no name value pair.
   */

  private String toStringAnnotationValue(String name, Object value) {
    StringBuilder sb = new StringBuilder();
    sb.append(name).append("=");
    if (value instanceof Byte) {
      sb.append(((Byte) value).byteValue());
    } else if (value instanceof Boolean) {
      sb.append(((Boolean) value).booleanValue());
    } else if (value instanceof Character) {
      sb.append(((Character) value).charValue());
    } else if (value instanceof Short) {
      sb.append(((Short) value).shortValue());
    } else if (value instanceof Integer) {
      sb.append(((Integer) value).intValue());
    } else if (value instanceof Long) {
      sb.append(((Long) value).longValue());
    } else if (value instanceof Float) {
      sb.append(((Float) value).floatValue());
    } else if (value instanceof Double) {
      sb.append(((Double) value).doubleValue());
    } else if (value instanceof String) {
      sb.append(((String) value));
    } else if (value instanceof Type) {
      sb.append(((Type) value).getClassName());
    } else if (value instanceof String[]) {
      String[] ss = (String[]) value;
      sb.append(ss[0]).append(ss[1]);
    } else if (value instanceof AnnotationNode) {
      sb.append(toStringAnnotation((AnnotationNode) value));
    } else if (value instanceof List) {
      throw new IllegalStateException("nyi");
    }
    return sb.toString().trim();
  }

  private static class SimpleOutputStream extends OutputStream {

    StringBuilder sb = new StringBuilder();

    @Override
    public void write(int b) throws IOException {
      sb.append((char) b);
    }

    @Override
    public String toString() {
      return sb.toString();
    }

  }

  protected static String getStamp(ClassLoader loader, String classname) {
    Assert.assertFalse(classname.endsWith(".class"));
    Assert.assertEquals(-1, classname.indexOf('/'));
    URL resourceURL = loader.getResource(classname.replace('.', '/') + ".class");
    System.out.println(resourceURL.getFile());
    return null;
  }

  /**
   * Look for a <name>.print file and check the printout of the bytes matches it, unless regenerate is true in which case the
   * print out is recorded in that file.
   */
  protected void checkIt(String name, byte[] bytes) {
    checkIt(name, bytes, shouldRegenerate());
  }

  /**
   * Look for a <name>.print file and check the printout of the bytes matches it, unless regenerate is true in which case the
   * print out is recorded in that file.
   */
  protected void checkIt(String name, byte[] bytes, boolean regenerate) {
    String filename = "src/test/java/" + name.replace('.', '/') + ".print";
    try {
      if (regenerate) {
        // create the file
        System.out.println("creating " + filename);
        File f = new File(filename);
        FileWriter fos = new FileWriter(f);
        BufferedWriter dos = new BufferedWriter(fos);
        dos.write(printItAndReturnIt(bytes));
        dos.flush();
        fos.close();
      } else {
        // compare the files
        List<String> expectedLines = new ArrayList<String>();
        File f = new File(filename);
        if (!f.exists()) {
          Assert.fail("Must run with renegerate on once to create the expected output for '" + name + "'");
        }
        FileInputStream fis = new FileInputStream(f);
        BufferedReader dis = new BufferedReader(new FileReader(new File(filename)));
        String line = null;
        while ((line = dis.readLine()) != null) {
          if (line.length() != 0) {
            expectedLines.add(line);
          }
        }
        dis.close();
        fis.close();
        List<String> actualLines = toLines(printItAndReturnIt(bytes));
        if (actualLines.size() != expectedLines.size()) {
          System.out.println("actual lines=" + actualLines.size());
          System.out.println("   exp lines=" + expectedLines.size());
          Assert.assertEquals(expectedLines, actualLines);
        }
        for (int ln = 0; ln < expectedLines.size(); ln++) {
          if (!expectedLines.get(ln).equals(actualLines.get(ln))) {
            String expLine = (ln + 1) + " " + expectedLines.get(ln);
            String actLine = (ln + 1) + " " + actualLines.get(ln);
            Assert.assertEquals(expLine, actLine);
          }
        }
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  protected List<String> toLines(String input) {
    StringTokenizer tokenizer = new StringTokenizer(input, "\n\r");
    List<String> output = new ArrayList<String>();
    while (tokenizer.hasMoreElements()) {
      output.add(tokenizer.nextToken());
    }
    return output;
  }

  protected boolean shouldRegenerate() {
    return true;
  }

  protected void copyFile(File from, File to) {
    try {
      FileInputStream fis = new FileInputStream(from);
      FileOutputStream fos = new FileOutputStream(to);
      BufferedInputStream bis = new BufferedInputStream(fis);
      BufferedOutputStream bos = new BufferedOutputStream(fos);
      byte[] buffer = new byte[4096];
      int len;
      while ((len = bis.read(buffer, 0, 4096)) != -1) {
        bos.write(buffer, 0, len);
      }
      bis.close();
      bos.close();
    } catch (IOException ioe) {
      throw new RuntimeException("Copy file failed", ioe);
    }
  }

  protected void checkMethod(byte[] bytes, String name, String expected) {
    String actual = toStringMethod(bytes, name, false);
    if (!actual.equals(expected)) {
      // print it out for inclusion in the testcode
      System.out.println(toStringMethod(bytes, name, true));
    }
    Assert.assertEquals(expected, actual);
  }

  protected void checkType(byte[] bytes, String expected) {
    String actual = printItAndReturnIt(bytes, false);
    if (!actual.equals(expected)) {
      // print it out for inclusion in the testcode
      System.out.println(printItAndReturnIt(bytes, true));
    }
    Assert.assertEquals(expected, actual);
  }

  // ---

  // private void loadNewVersion(ReloadableType rtype, String version) throws InstantiationException,
  // IllegalAccessException {
  // loadNewVersion(rtype, version, true);
  // }
  //
  // /**
  // * Loads a new version of a type, given the name of the type, the version (suffix) and the name.
  // */
  // private void loadNewVersion(ReloadableType rtype, String version, boolean log) throws InstantiationException,
  // IllegalAccessException {
  // String name = rtype.getTypeName();
  // byte[] newclassbytes = retrieveClass(name + version);
  // newclassbytes = ClassRenamer.rename(name.replace('.', '/'), newclassbytes);
  // byte[] newdispatcher = DispatcherCreator.createFor(rtype, version);
  // if (log) {
  // System.out.println("DISPATCHER:");
  // print(newdispatcher);
  // }
  // Class<?> newdispatcherclass = loadit(name + "$D$" + version, newdispatcher);
  // byte[] newexecutorbytes = ExecutorCreator.createFor(rtype, version, newclassbytes);
  // if (log) {
  // System.out.println("EXECUTOR:");
  // print(newexecutorbytes);
  // }
  // loadit(name + "$E$" + version, newexecutorbytes);
  // TypeRegistry.poke(name.replace('.', '/'), newdispatcherclass.newInstance());
  // }
  //
  // private void checkvalue(Class<?> clazz, String methodname, Object expectedOutput) {
  // Object value = run(clazz, methodname);
  // if (!value.equals(expectedOutput)) {
  // Assert.fail("Expected " + expectedOutput + ", not " + value);
  // }
  // }

  protected void configureForTesting(TypeRegistry typeRegistry, String... includePatterns) {
    if (includePatterns != null) {
      Properties p = new Properties();
      StringBuilder s = new StringBuilder();
      for (int i = 0; i < includePatterns.length; i++) {
        if (i > 0) {
          s.append(',');
        }
        s.append(includePatterns[i]);
      }
      p.setProperty(TypeRegistry.Key_Inclusions, s.toString());
      typeRegistry.configure(p);
    }
  }

  protected void checkCause(Exception e, Class<? extends Throwable> expectedCause) {
    Throwable t = e.getCause();
    if (t == null || !t.getClass().equals(expectedCause)) {
      e.printStackTrace();
      Assert.fail("Expected cause of " + expectedCause + " but it was " + (t == null ? "null" : t.getClass()));
    }
  }

  public MethodMember grabFrom(List<MethodMember> ms, String name) {
    for (MethodMember m : ms) {
      if (m.getName().equals(name)) {
        return m;
      }
    }
    return null;
  }

  public Method grabFrom(Method[] ms, String name) {
    for (Method m : ms) {
      if (m.getName().equals(name)) {
        return m;
      }
    }
    return null;
  }

  public Field grabFrom(Field[] fs, String name) {
    for (Field f : fs) {
      if (f.getName().equals(name)) {
        return f;
      }
    }
    return null;
  }

  protected MethodMember findMethod(String toSearchFor, TypeDescriptor typeDescriptor) {
    for (MethodMember method : typeDescriptor.getMethods()) {
      if (method.toString().equals(toSearchFor)) {
        return method;
      }
    }
    return null;
  }

  /**
   * Create a type registry, configure it with the specified reloadable type/packages and return it.
   *
   * @return new TypeRegistry
   */
  protected TypeRegistry getTypeRegistry(String includePatterns) {
    TypeRegistry.reinitialize();
    TypeRegistry tr = TypeRegistry.getTypeRegistryFor(binLoader);
    Properties p = new Properties();
    if (includePatterns != null) {
      p.setProperty(TypeRegistry.Key_Inclusions, includePatterns);
    }
    if (tr == null) {
      throw new IllegalStateException(
          "maybe you need to run with: -Dspringloaded=limit=false -Xmx512M -XX:MaxPermSize=256m -noverify");
    }
    tr.configure(p);
    return tr;
  }

  //  protected TypeRegistry getTypeRegistry(String... includePatterns) {
  //    StringBuilder s = new StringBuilder();
  //    for (int i = 0; i < includePatterns.length; i++) {
  //      if (i > 0) {
  //        s.append(',');
  //      }
  //      s.append(includePatterns[i]);
  //    }
  //    return getTypeRegistry(s.toString());
  //  }

  protected TypeRegistry getTypeRegistry() {
    return getTypeRegistry(null);
  }

  /**
   * Make a type reload itself - this does trigger creation of the dispatcher/executor.
   */
  protected void reload(ReloadableType reloadableType, String versionstamp) {
    reloadableType.loadNewVersion(versionstamp, reloadableType.bytesInitial);
  }

  @SuppressWarnings("unchecked")
  protected void checkLocalVariables(byte[] bytes, String methodNameAndDescriptor, String... expected) {
    ClassNode cn = new ClassNode();
    ClassReader cr = new ClassReader(bytes);
    cr.accept(cn, 0);

    boolean checked = false;
    List<MethodNode> methods = cn.methods;
    for (MethodNode mn : methods) {
      if (methodNameAndDescriptor.equals(mn.name + mn.desc)) {
        List<LocalVariableNode> localVariables = mn.localVariables;
        Assert.assertEquals(expected.length, localVariables.size());
        for (int i = 0; i < expected.length; i++) {
          StringTokenizer tokenizer = new StringTokenizer(expected[i], ":");
          String expectedName = tokenizer.nextToken();
          String expectedDesc = tokenizer.nextToken();
          LocalVariableNode localVariable = localVariables.get(i);
          Assert.assertEquals(i, localVariable.index);
          Assert.assertEquals(expectedName, localVariable.name);
          Assert.assertEquals(expectedDesc, localVariable.desc);
        }
        checked = true;
      }
    }
    if (!checked) {
      for (MethodNode mn : methods) {
        System.out.println(mn.name + mn.desc);
      }
      Assert.fail("Unable to find method " + methodNameAndDescriptor);
    }
  }

  @SuppressWarnings("unchecked")
  protected void checkAnnotations(byte[] bytes, String methodNameAndDescriptor, String... expected) {
    ClassNode cn = new ClassNode();
    ClassReader cr = new ClassReader(bytes);
    cr.accept(cn, 0);
    if (expected == null) {
      expected = new String[0];
    }

    boolean checked = false;
    List<MethodNode> methods = cn.methods;
    for (MethodNode mn : methods) {
      if (methodNameAndDescriptor.equals(mn.name + mn.desc)) {
        List<AnnotationNode> annotations = mn.visibleAnnotations;
        if (annotations == null) {
          annotations = Collections.emptyList();
        }
        Assert.assertEquals(expected.length, annotations.size());
        for (int i = 0; i < expected.length; i++) {
          //          StringTokenizer tokenizer = new StringTokenizer(expected[i], ":");
          //          String expectedName = tokenizer.nextToken();
          //          String expectedDesc = tokenizer.nextToken();
          AnnotationNode annotation = annotations.get(i);
          Assert.assertEquals(expected[i], toString(annotation));
        }
        checked = true;
      }
    }
    if (!checked) {
      for (MethodNode mn : methods) {
        System.out.println(mn.name + mn.desc);
      }
      Assert.fail("Unable to find method " + methodNameAndDescriptor);
    }
  }

  @SuppressWarnings({ "rawtypes" })
  protected Object toString(AnnotationNode annotation) {
    StringBuilder s = new StringBuilder();
    s.append("@");
    String s2 = annotation.desc.substring(1, annotation.desc.length() - 1);
    s.append(s2.replace('/', '.'));
    s.append("(");
    List values = annotation.values;
    if (values != null) {
      int i = 0;
      while (i < values.size()) {
        String name = (String) values.get(i++);
        Object value = values.get(i++);
        s.append(name).append("=").append(value);
      }
    }
    s.append(")");
    return s.toString();
  }

  protected void assertStartsWith(String prefix, Object value) {
    String stringValue = (String) value;
    if (!stringValue.startsWith(prefix)) {
      Assert.fail("Expected 'regular' toString() but was " + result.returnValue);
    }
  }

  protected void checkDoesNotContain(TypeDescriptor typeDescriptor, String string) {
    if (typeDescriptor.toString().indexOf(string) != -1) {
      Assert.fail("Did not expect to find '" + string + "' in\n" + typeDescriptor);
    }
  }

  protected void checkDoesContain(TypeDescriptor typeDescriptor, String string) {
    if (typeDescriptor.toString().indexOf(string) == -1) {
      Assert.fail("Expected to find '" + string + "' in\n" + typeDescriptor);
    }
  }

  protected ReloadableType loadType(TypeRegistry typeRegistry, String dottedTypeName) {
    return typeRegistry.addType(dottedTypeName, loadBytesForClass(dottedTypeName));
  }

  public Class<?> classForName(String typeName) throws ClassNotFoundException {
    if (typeName.endsWith("[]")) {
      Class<?> element = classForName(typeName.substring(0, typeName.length() - 2));
      return Array.newInstance(element, 0).getClass();
    } else if (typeName.equals("int")) {
      return int.class;
    } else if (typeName.equals("void")) {
      return void.class;
    } else if (typeName.equals("boolean")) {
      return boolean.class;
    } else if (typeName.equals("byte")) {
      return byte.class;
    } else if (typeName.equals("char")) {
      return char.class;
    } else if (typeName.equals("short")) {
      return short.class;
    } else if (typeName.equals("double")) {
      return double.class;
    } else if (typeName.equals("float")) {
      return float.class;
    } else if (typeName.equals("long")) {
      return long.class;
    }
    return Class.forName(typeName, false, binLoader);
  }

  protected Object intArrayToString(Object value) {
    int[] intArray = (int[]) value;
    StringBuilder s = new StringBuilder();
    s.append("{");
    if (intArray != null) {
      for (int j = 0; j < intArray.length; j++) {
        if (j > 0) {
          s.append(",");
        }
        s.append(intArray[j]);
      }
    }
    s.append("}");
    return s.toString();
  }

  protected String objectArrayToString(Object value) {
    Object[] array = (Object[]) value;
    StringBuilder s = new StringBuilder();
    s.append("{");
    if (array != null) {
      for (int j = 0; j < array.length; j++) {
        if (j > 0) {
          s.append(",");
        }
        s.append(array[j]);
      }
    }
    s.append("}");
    return s.toString();
  }

  protected void assertContains(String expectedToBeContained, String actual) {
    if (actual.indexOf(expectedToBeContained) == -1) {
      fail("\nCould not find expected data:\n" + expectedToBeContained + "\n in actual output:\n" + actual);
    }
  }

  protected void assertUniqueContains(String expectedToBeContained, String actual) {
    if (actual.indexOf(expectedToBeContained) == -1
        || actual.indexOf(expectedToBeContained) != actual.lastIndexOf(expectedToBeContained)) {
      fail("Expected a unique occurrence of:\n" + expectedToBeContained + "\n in actual output:\n" + actual);
    }
  }

  protected void assertDoesNotContain(String expectedToBeContained, String actual) {
    if (actual.indexOf(expectedToBeContained) != -1) {
      fail("Did not expect to find data:\n" + expectedToBeContained + "\n in actual output:\n" + actual);
    }
  }

  protected ISMgr getFieldAccessor(Object o) {
    Class<?> clazz = o.getClass();
    try {
      Field f = clazz.getDeclaredField(Constants.fInstanceFieldsName);
      f.setAccessible(true);
      return (ISMgr) f.get(o);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  protected String getStaticFieldsMap(Class<?> clazz) {
    try {
      Field f = clazz.getDeclaredField(Constants.fStaticFieldsName);
      f.setAccessible(true);
      SSMgr m = (SSMgr) f.get(null);
      return m.toString();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  PrintStream oldo, olde;
  ByteArrayOutputStream oso, ose;

  /**
   * Start intercepting the System.out/System.err streams
   */
  protected void captureOn() {
    oldo = System.out;
    olde = System.err;
    oso = new ByteArrayOutputStream();
    ose = new ByteArrayOutputStream();
    System.setOut(new PrintStream(oso));
    System.setErr(new PrintStream(ose));
  }

  protected static String toSlash(String dottedName) {
    return dottedName.replace('.', '/');
  }

  protected static String toDotted(String slashedName) {
    return slashedName.replace('/', '.');
  }

  /**
   * Stop intercepting the System.out/System.err streams and return any accumulated output since the captureOn.
   */
  protected String captureOff() {
    if (oldo == null) {
      throw new IllegalStateException("Turning capture off without having turned it on");
    }
    System.setOut(oldo);
    System.setErr(olde);
    oldo = null;
    olde = null;
    return new String("SYSOUT\n" + oso.toString().replace("\r", "") + "\nSYSERR\n" + ose.toString().replace("\r", "") + "\n");
  }

  protected String captureOffReturnStdout() {
    if (oldo == null) {
      throw new IllegalStateException("Turning capture off without having turned it on");
    }
    System.setOut(oldo);
    System.setErr(olde);
    oldo = null;
    olde = null;
    return new String(oso.toString());
  }

  /**
   * Called at the end of a test to tidy up in case a test crashed and failed to stop capturing.
   */
  protected void ensureCaptureOff() {
    if (oldo != null) {
      System.setOut(oldo);
      System.setErr(olde);
      oldo = null;
    }
  }

  /**
   * Execute a specific method, returning all output that occurred during the run to the caller.
   */
  public String runMethodAndCollectOutput(Class<?> clazz, String methodname) throws Exception {
    captureOn();
    Method m = clazz.getDeclaredMethod(methodname);
    if (!Modifier.isStatic(m.getModifiers())) {
      fail("Method should be static: " + m);
    }
    m.invoke(null);
    return captureOff();
  }

  protected String slashed(String dotted) {
    return dotted.replaceAll("\\.", "/");
  }

  protected final static void pause(int seconds) {
    try {
      Thread.sleep(seconds*1000);
    } catch (Exception e) {}
  }
 
  protected void assertStdout(String expectedStdout, JVMOutput actualOutput) {
    if (!expectedStdout.equals(actualOutput.stdout)) {
      //      assertEquals(expectedStdout, actualOutput.stdout);
      fail("Expected stdout '" + expectedStdout + "' not found in \n" + actualOutput.toString());
    }
  }
 
  protected void assertStdoutContains(String expectedStdout, JVMOutput actualOutput) {
    if (!actualOutput.stdout.contains(expectedStdout)) {
      fail("Expected stdout:\n" + expectedStdout + "\nbut was:\n" + actualOutput.stdout.toString()+"\nComplete output: \n"+actualOutput.toString());
    }
  }
 
  protected void assertStdoutContains(String expectedStdout, Result r) {
    // TODO Auto-generated method stub
   
  }


  protected void assertStderrContains(String expectedStderrContains, JVMOutput actualOutput) {
    if (actualOutput.stderr.indexOf(expectedStderrContains) == -1) {
      fail("Expected stderr to contain '" + expectedStderrContains + "'\n" + actualOutput.toString());
    }
  }
 
}
TOP

Related Classes of org.springsource.loaded.test.SpringLoadedTests

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.