package net.ssehub.kernel_haven;

import java.io.File;
import java.io.IOException;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import net.ssehub.kernel_haven.util.Util;

/**
 * Abstract superclass for all scenario tests. This sets up the proper test environment and executes the pipeline.
 * Subclasses can override the check*() methods for assertions on the output.
 *
 * @author Adam
 */
@SuppressWarnings("null")
public abstract class AbstractScenarioTest {

    private File resDir;
    
    private File cacheDir;
    
    private File outputDir;
    
    private File pluginsDir;
    
    private File logDir;
    
    private File srcTree;
    
    /**
     * Creates the necessary temporary directories.
     * 
     * @throws IOException unwanted.
     */
    @Before
    public void setUp() throws IOException {
        resDir = new File("testdata", getClass().getSimpleName() + ".res");
        cacheDir = new File("testdata", getClass().getSimpleName() + ".cache");
        outputDir = new File("testdata", getClass().getSimpleName() + ".output");
        logDir = new File("testdata", getClass().getSimpleName() + ".log");
        pluginsDir = new File("testdata", getClass().getSimpleName() + ".plugins");
        srcTree = new File("testdata", getClass().getSimpleName() + ".src");

        if (resDir.exists()) {
            Util.deleteFolder(resDir);
        }
        if (cacheDir.exists()) {
            Util.deleteFolder(cacheDir);
        }
        if (outputDir.exists()) {
            Util.deleteFolder(outputDir);
        }
        if (logDir.exists()) {
            Util.deleteFolder(logDir);
        }
        if (pluginsDir.exists()) {
            Util.deleteFolder(pluginsDir);
        }
        if (srcTree.exists()) {
            Util.deleteFolder(srcTree);
        }
        
        resDir.mkdir();
        cacheDir.mkdir();
        outputDir.mkdir();
        logDir.mkdir();
        pluginsDir.mkdir();
        copyFolder(getSourceTree(), srcTree);
    }
    
    /**
     * Deep-copies a folder to a destination.
     * 
     * @param src The source to copy.
     * @param dst The destination to copy to.
     * 
     * @throws IOException If copying fails.
     */
    private void copyFolder(File src, File dst) throws IOException {
        if (src.isDirectory()) {
            dst.mkdir();
            for (File file : src.listFiles()) {
                copyFolder(file, new File(dst, file.getName()));
            }
            
        } else {
            Util.copyFile(src, dst);
        }
    }
    
    /**
     * Main test method. Executes KernelHaven and calls the check*() methods.
     * 
     * @throws Exception unwanted.
     */
    @Test
    public void run()
        // CHECKSTYLE:OFF // we allow throws exception here
            throws Exception {
        // CHECKSTYLE:ON
        boolean success = Run.run(getPropertiesFile().getPath());
        Assert.assertTrue(success);
        //assertThat(success, is(true));
        
        checkOutputDirResult(outputDir);
        checkCacheDirResult(cacheDir);
        checkLogDirResult(logDir);
        checkResDirResult(resDir);
    }
    
    /**
     * Defines which property file to use. This file should contain the following lines:
     * <code><pre>
     * source_tree = testdata/tmpSrc
     * resource_dir = testdata/tmpRes
     * cache_dir = testdata/tmpCache
     * output_dir = testdata/tmpOutput
     * plugins_dir = testdata/tmpPlugins
     * log.dir = testdata/tmpLog
     * </pre></code>
     * 
     * @return The property file to use.
     */
    protected abstract File getPropertiesFile();
    
    /**
     * Returns the source tree to analyze. This will be copied for a test run, to avoid modifications to the original.
     * 
     * @return The source tree to analyze.
     */
    protected abstract File getSourceTree();
    
    /**
     * Optionally does some post-checks on the resource directory.
     * 
     * @param dir The resource directory.
     * 
     * @throws Exception unwanted.
     */
    protected void checkResDirResult(File dir)
        // CHECKSTYLE:OFF // we allow throws exception here
            throws Exception {
        // CHECKSTYLE:ON
    }
    
    /**
     * Optionally does some post-checks on the output directory.
     * 
     * @param dir The output directory.
     * 
     * @throws Exception unwanted.
     */
    protected void checkOutputDirResult(File dir)
        // CHECKSTYLE:OFF // we allow throws exception here
            throws Exception {
        // CHECKSTYLE:ON
    }
    
    /**
     * Optionally does some post-checks on the cache directory.
     * 
     * @param dir The cache directory.
     * 
     * @throws Exception unwanted.
     */
    protected void checkCacheDirResult(File dir)
        // CHECKSTYLE:OFF // we allow throws exception here
            throws Exception {
        // CHECKSTYLE:ON
    }
    
    /**
     * Optionally does some post-checks on the log directory.
     * 
     * @param dir The log directory.
     * 
     * @throws Exception unwanted.
     */
    protected void checkLogDirResult(File dir)
        // CHECKSTYLE:OFF // we allow throws exception here
            throws Exception {
        // CHECKSTYLE:ON
    }
    
}

@@ -3314,12 +3314,19 @@
 ata/
-tmpS
+CLASSNAME.s
 rc%0A 
@@ -3359,12 +3359,19 @@
 ata/
-tmpR
+CLASSNAME.r
 es%0A 
@@ -3401,12 +3401,19 @@
 ata/
-tmpC
+CLASSNAME.c
 ache
@@ -3446,12 +3446,19 @@
 ata/
-tmpO
+CLASSNAME.o
 utpu
@@ -3493,12 +3493,20 @@
 ata/
-tmpP
+/CLASSNAME.p
 lugi
@@ -3538,12 +3538,20 @@
 ata/
-tmpL
+/CLASSNAME.l
 og%0A 
@@ -3618,16 +3618,69 @@
  to use.
+ %3Cb%3EDefault:%3C/b%3E testdata/CLASSNAME/config.properties
 %0A     */
@@ -3690,33 +3690,24 @@
   protected 
-abstract 
 File getProp
@@ -3718,17 +3718,170 @@
 esFile()
-;
+ %7B%0A        return new File(%22testdata%22 + File.separatorChar + getClass().getSimpleName() + File.separatorChar%0A                + %22config.properties%22);%0A    %7D
 %0A    %0A  
@@ -4059,62 +4059,247 @@
 yze.
-%0A     */%0A    protected abstract File getS
+ %3Cb%3EDefault:%3C/b%3E testdata/CLASSNAME/source_tree%0A     */%0A    protected File getSourceTree() %7B%0A        return new File(%22testdata%22 + File.separatorChar + getClass().getSimpleName() + File.separatorChar%0A                + %22s
 ource
-Tree(
+_tree%22
 );%0A
+    %7D%0A
     

Add default implementations for getPropertiesFile() and getSourceTree()