package se.jiderhamn.classloader.leak.prevention;

import java.util.Collections;

import org.junit.Test;
import se.jiderhamn.classloader.leak.Leaks;

/**
 * Abstract base class for testing {@link ClassLoaderPreMortemCleanUp} implementations.
 * TODO Move this to test framework(?)
 * @author Mattias Jiderhamn
 */
public abstract class ClassLoaderPreMortemCleanUpTestBase {
  
  /** 
   * Test case that verifies that {@link #triggerLeak()} indeed does cause a leak, in case the
   * {@link ClassLoaderPreMortemCleanUp} is not executed.
   */
  @SuppressWarnings("DefaultAnnotationParam")
  @Test
  @Leaks(true) // Without the cleanup we should expect a leak
  public void triggerLeakWithoutCleanup() throws Exception {
    triggerLeak();
  }
  
  @Test
  @Leaks(false) // After having run the cleanup, there should be no leak
  public void cleanUpAfterTriggeringLeak() throws Exception {
    triggerLeak();
    getClassLoaderPreMortemCleanUp().cleanUp(getClassLoaderLeakPreventor());
  }
  
  /** Concrete tests should implement this method to trigger the leak */
  protected abstract void triggerLeak() throws Exception;
  
  /** 
   * Concrete tests should implement this method to return a {@link ClassLoaderPreMortemCleanUp} 
   * that will clean up after the leak triggered by {@link #triggerLeak()}, so that {@link ClassLoader} can be
   * garbage collected.
   */
  protected abstract ClassLoaderPreMortemCleanUp getClassLoaderPreMortemCleanUp();

  /**
   * Concrete tests may override this method, in case they to provide a specific {@link ClassLoaderLeakPreventor}
   * to the {@link ClassLoaderPreMortemCleanUp}.
   * @return
   */
  @SuppressWarnings("WeakerAccess")
  protected ClassLoaderLeakPreventor getClassLoaderLeakPreventor() {
    return new ClassLoaderLeakPreventor(getClass().getClassLoader().getParent(),
        getClass().getClassLoader(),
        new LoggerImpl(), 
        Collections.<PreClassLoaderInitiator>emptyList(),
        Collections.<ClassLoaderPreMortemCleanUp>emptyList());
  }
  
}
@@ -60,48 +60,186 @@
 ava.
-util.Collections;%0A%0Aimport org.junit.Test
+lang.reflect.ParameterizedType;%0Aimport java.util.Collections;%0A%0Aimport org.junit.Test;%0Aimport org.junit.runner.RunWith;%0Aimport se.jiderhamn.classloader.leak.JUnitClassloaderRunner
 ;%0Aim
@@ -445,16 +445,55 @@
 amn%0A */%0A
+@RunWith(JUnitClassloaderRunner.class)%0A
 public a
@@ -541,16 +541,55 @@
 TestBase
+%3CC extends ClassLoaderPreMortemCleanUp%3E
  %7B%0A  %0A  
@@ -1362,32 +1362,28 @@
 e tests 
-should implement
+may override
  this me
@@ -1579,92 +1579,647 @@
    *
-/%0A  protected abstract ClassLoaderPreMortemCleanUp getClassLoaderPreMortemCleanUp();
+ The default implementation will use the generics parameter type information.%0A   */%0A  protected C getClassLoaderPreMortemCleanUp() throws IllegalAccessException, InstantiationException %7B%0A    ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();%0A    Object actualType = genericSuperclass.getActualTypeArguments()%5BgenericSuperclass.getActualTypeArguments().length - 1%5D;%0A    %0A    Class%3CC%3E cleanUpImplClass = (actualType instanceof ParameterizedType) ? %0A        (Class%3CC%3E) ((ParameterizedType)actualType).getRawType() :%0A        (Class%3CC%3E) actualType;%0A      %0A    return cleanUpImplClass.newInstance();%0A  %7D
 %0A%0A  

Update ClassLoaderPreMortemCleanUpTestBase to support generics and by default create ClassLoaderPreMortemCleanUp instance from generic type parameter. #43