Package uk.ac.uea.threadr.internal.testing

Source Code of uk.ac.uea.threadr.internal.testing.SafetyTester

package uk.ac.uea.threadr.internal.testing;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;

import uk.ac.uea.threadr.ThreadSafety;
import uk.ac.uea.threadr.ThreadTest;
import uk.ac.uea.threadr.Threadr;
import uk.ac.uea.threadr.internal.testing.tests.MemberTest;
import uk.ac.uea.threadr.internal.testing.tests.SerializableTest;
import uk.ac.uea.threadr.internal.testing.tests.StaticTester;

/**
* Tests the thread safety of Java objects using a set of tests described using
*  the {@link ThreadTest} interface provided by the Threadr API. The results
* of the testing are returned as a value from the {@link ThreadSafety} enum.
*
* @author Jordan Woerner
* @version 1.2
*/
public class SafetyTester {

  private static final Logger logger = Threadr.logger;
 
  /** A List of ThreadTests to use when testing for thread safety. */
  private Set<ThreadTest> tests;
  /** The safety of the thread tests. */
  private ThreadSafety safety;
 
  /**
   * Sets up the SafetyTester loading all the tests provided by the
   * framework.
   *
   * @since 1.0
   */
  public SafetyTester() {
   
    this.tests = new HashSet<>();
    this.safety = ThreadSafety.THREAD;
   
    tests.add(new StaticTester());
    tests.add(new MemberTest());
  }
 
  /**
   * Passes the SafetyTester a list of tests from outside of the framework.
   *
   * <p>The {@link Set} of tests are required to implement the
   * {@link ThreadTest} interface to be accepted.</p>
   *
   * @param newTests A List of tests derived from the ThreadTest interface.
   * @since 1.0
   */
  public void provideTests(Set<? extends ThreadTest> newTests) {
   
    for (Object test : newTests) {
      this.tests.add((ThreadTest)test);
    }
  }
 
  /**
   * Test the safety of the provided class using the tests know by this
   * SafetyTester.
   *
   * @param obj The {@link Object} to test for thread safeness.
   * @return Returns a value from the {@link ThreadSafety} enum. Returns
   * {@link ThreadSafety#THREAD} if the class being tested is thread safe,
   * {@link ThreadSafety#VM} if the class being tested can be run in a new Java
   *  Virtual Machine instance, or {@link ThreadSafety#SEQUENTIAL} if the class
   *  cannot be run in parallel in any manner.
   * @since 1.0
   */
  public ThreadSafety testSafety(final Object obj) {
   
    this.safety = ThreadSafety.THREAD; // Reset the safety every run.
   
    List<Class<?>> failedTests = new ArrayList<>();
    Class<?> clazz = obj.getClass();
    logger.fine(String.format("Testing: %s", clazz.getName()));
   
    /* Use every test provided to see if the class is thread safe. */
    for (Object t : tests) {
      ThreadTest test = (ThreadTest)t;
      ThreadSafety result = test.test(clazz);
      if (result != ThreadSafety.THREAD) {
        /* Any test that is not thread safe is failed. */
        failedTests.add(test.getClass());
      }
      /* If a result was returned, and it's worse than the stored one. */
      if (result != null
          && (result.val() < safety.val())) {
        safety = result; // Set the new safety result.
      }
    }
   
    /* Check the task can be serialised if it's VM safe. */
    if (safety == ThreadSafety.VM
      && !isSerialisabe(obj)) {
      /* If a task cannot be serialised, it's unsafe. */
      safety = ThreadSafety.SEQUENTIAL;
    }
   
    /* Print out the thread safeness of the class. */
    switch (safety) {
    case SEQUENTIAL:
      logger.info(String.format("Class %s - Sequential safe",
          clazz.getName()));
      break;
    case THREAD:
      logger.info(String.format("Class %s - Thread safe",
          clazz.getName()));
      break;
    case VM:
      logger.info(String.format("Class %s - Virtual Machine safe",
          clazz.getName()));
      break;
    default:
      logger.info(String.format("Unknown test result for class %s",
          clazz.getName()));
    }
    /* Print any failed tests to the loggers fine output. */
    if (failedTests.size() > 0) {
      StringBuilder errors = new StringBuilder("Failed tests:\n");
      for (Class<?> test : failedTests) {
        errors.append('\t').append(test.getName()).append('\n');
      }
     
      logger.fine(errors.toString());
    }
   
    return safety; // Return the thread safeness of the class.
  }
 
  /**
   * Tests a provided object to see if it can be serialised and
   * de-serialised safely.
   *
   * @param object The Object to test.
   * @return Returns true if the Object serialised fully and safely, false
   * otherwise.
   * @since 1.2
   */
  public boolean isSerialisabe(Object object) {
   
    return new SerializableTest().test(object);
  }
}
TOP

Related Classes of uk.ac.uea.threadr.internal.testing.SafetyTester

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.