Package org.junitext.internal.runners

Source Code of org.junitext.internal.runners.PrerequisiteHandler

/*******************************************************************************
* Copyright (C) 2006-2007 Jochen Hiller and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License - v 1.0
* which accompanies this distribution, and is available at
* http://junitext.sourceforge.net/licenses/junitext-license.html
*
* Contributors:
*     Jochen Hiller - initial API and implementation
******************************************************************************/
package org.junitext.internal.runners;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.StringTokenizer;

import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.junitext.Prerequisite;

/**
* Handler class for all prerequite handling.
*/
public class PrerequisiteHandler {

  // static methods

  public static String getClassName(Description description) {
    // ugly code: parse from string representation :(
    String name = description.getDisplayName();
    StringTokenizer tokenizer = new StringTokenizer(name, "(");
    // next token is: methodName, we ignore
    tokenizer.nextToken();
    String className = tokenizer.nextToken(")").substring(1);
    return className;
  }

  public static String getMethodName(Description description) {
    // ugly code: parse from string representation :(
    String name = description.getDisplayName();
    StringTokenizer tokenizer = new StringTokenizer(name, "(");
    String methodName = tokenizer.nextToken();
    return methodName;
  }

  // public methods

  public boolean shouldRun(Description description, Object fTest) {
    return shouldRun(description, fTest, null);
  }

  public boolean shouldRun(Description description, Object fTest,
      RunNotifier notifier) {
    try {
      Class<?> clazz = Class.forName(PrerequisiteHandler
          .getClassName(description));
      Method m = clazz.getMethod(PrerequisiteHandler
          .getMethodName(description));

      Prerequisite prereq = m.getAnnotation(Prerequisite.class);
      if (prereq != null) {
        // if prereq defined, handle it
        // no notifier available here
        return handleAnnotation(description, fTest, prereq, notifier);
      } else {
        // else shouldRun=true
        return true;
      }
    } catch (Exception e) {
      Exception internalEx = new Exception(
          "Internal error when checking prerequisite", e);
      // TODO: how can we indicate this as an error ? throw an exception ?
      // No notifier available
      // fNotifier.fireTestFailure(new Failure(methodDescription(fMethod),
      // internalEx));
      internalEx.printStackTrace();
      return false;
    }
  }

  public boolean handleAnnotation(Description description, Object testObject,
      Annotation prereq, RunNotifier notifier) {
    try {
      boolean isFulfilled = checkPrerequisite(description, testObject,
          (Prerequisite) prereq);
      if (isFulfilled) {
        return true;
      } else {
        // to simplify, call fire testIgnore
        // see also {@link Prerequisite} design question 2
        if (notifier != null) {
          notifier.fireTestIgnored(description);
        }
        return false;
      }
    } catch (Exception e) {
      Exception internalEx = new Exception(
          "Internal error when checking prerequisite", e);
      if (notifier != null) {
        notifier.fireTestFailure(new Failure(description, internalEx));
      }
      return false;
    }
  }

  protected boolean checkPrerequisite(Description desc, Object testObject,
      Prerequisite prereq) throws Exception {
    String prereqName = prereq.requires();
    Class<?> classToRetrievePrerequisite = prereq.callee();

    // defaults to invoke of class method
    Object objectToInvoke = null;
    // if class is default value: use current instance
    if (Prerequisite.NoCallee.class == classToRetrievePrerequisite) {
      classToRetrievePrerequisite = testObject.getClass();
      objectToInvoke = testObject;
    }
    // test all supported reflection calls. Priority:
    // - description
    // - className, methodName
    // - void
    HandleState state = handleDescription(classToRetrievePrerequisite,
        prereqName, desc, objectToInvoke);
    if (state.equals(HandleState.NotHandled)) {
      state = handleClassNameMethodName(classToRetrievePrerequisite,
          prereqName, desc, objectToInvoke);
      if (state.equals(HandleState.NotHandled)) {
        state = handleVoidMethod(classToRetrievePrerequisite,
            prereqName, desc, objectToInvoke);
        // state = handleClassMethod();
      }
    }
    switch (state) {
    case False:
      return false;
    case True:
      return true;
    case NotHandled:
    default:
      // Hmm: compiler error? Will not understand, that enum is complete!
      // See Sun: 879666 - Compiler does not understand execution paths
      // for enum and switch statements
      throw new Exception(
          "Could not find prerequisite method with support Signatures.");
    }
  }

  /**
   * Handle call to methods with signature
   * {@code public boolean isSomething()}.
   */
  protected HandleState handleVoidMethod(Class<?> clazz, String prereqName,
      Description desc, Object testObject) {
    try {
      // call method to object, must not have arguments
      Method methodToCall = clazz.getMethod(prereqName, new Class[] {});
      Object prereqRet = methodToCall.invoke(testObject, new Object[] {});
      if (prereqRet.getClass() != Boolean.class) {
        // wrong return type
        // System.out.println("Prerequisite is not valid, must return
        // boolean");
        return HandleState.NotHandled;
      }
      boolean b = ((Boolean) prereqRet).booleanValue();
      return b ? HandleState.True : HandleState.False;
    } catch (SecurityException e) {
      // ignore here
    } catch (NoSuchMethodException e) {
      // ignore here
    } catch (IllegalArgumentException e) {
      // ignore here
    } catch (IllegalAccessException e) {
      // ignore here
    } catch (InvocationTargetException e) {
      // ignore here
    }
    return HandleState.NotHandled;
  }

  /**
   * Handle call to methods with signature
   * {@code public boolean isSomething(String className, String methodName)}.
   */
  protected HandleState handleClassNameMethodName(Class<?> clazz,
      String prereqName, Description description, Object testObject) {
    try {
      // call method to object, must not have arguments
      Method methodToCall = clazz.getMethod(prereqName, new Class[] {
          String.class, String.class });
      Object prereqRet = methodToCall.invoke(testObject, new Object[] {
          PrerequisiteHandler.getClassName(description),
          PrerequisiteHandler.getMethodName(description) });
      if (prereqRet.getClass() != Boolean.class) {
        // wrong return type
        // System.out.println("Prerequisite is not valid, must return
        // boolean");
        return HandleState.NotHandled;
      }
      boolean b = ((Boolean) prereqRet).booleanValue();
      return b ? HandleState.True : HandleState.False;
    } catch (SecurityException e) {
      // ignore here
    } catch (NoSuchMethodException e) {
      // ignore here
    } catch (IllegalArgumentException e) {
      // ignore here
    } catch (IllegalAccessException e) {
      // ignore here
    } catch (InvocationTargetException e) {
      // ignore here
    }
    return HandleState.NotHandled;
  }

  /**
   * Handle call to methods with signature
   * {@code public boolean isSomething(Description desc)}.
   */
  protected HandleState handleDescription(Class<?> clazz, String prereqName,
      Description description, Object testObject) {
    try {
      // call method to object, must not have arguments
      Method methodToCall = clazz.getMethod(prereqName,
          new Class[] { Description.class });
      Object prereqRet = methodToCall.invoke(testObject,
          new Object[] { description });
      if (prereqRet.getClass() != Boolean.class) {
        // wrong return type
        // System.out.println("Prerequisite is not valid, must return
        // boolean");
        return HandleState.NotHandled;
      }
      boolean b = ((Boolean) prereqRet).booleanValue();
      return b ? HandleState.True : HandleState.False;
    } catch (SecurityException e) {
      // ignore here
    } catch (NoSuchMethodException e) {
      // ignore here
    } catch (IllegalArgumentException e) {
      // ignore here
    } catch (IllegalAccessException e) {
      // ignore here
    } catch (InvocationTargetException e) {
      // ignore here
    }
    return HandleState.NotHandled;
  }

  // inner classes

  private enum HandleState {
    False, True, NotHandled;
  }
}
TOP

Related Classes of org.junitext.internal.runners.PrerequisiteHandler

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.