hu.bme.mit.sette.tools.spf.SpfGenerator.java Source code

Java tutorial

Introduction

Here is the source code for hu.bme.mit.sette.tools.spf.SpfGenerator.java

Source

/*
 * SETTE - Symbolic Execution based Test Tool Evaluator
 *
 * SETTE is a tool to help the evaluation and comparison of symbolic execution
 * based test input generator tools.
 *
 * Budapest University of Technology and Economics (BME)
 *
 * Authors: Lajos Cseppent <lajos.cseppento@inf.mit.bme.hu>, Zoltn Micskei
 * <micskeiz@mit.bme.hu>
 *
 * Copyright 2014
 *
 * 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 hu.bme.mit.sette.tools.spf;

import hu.bme.mit.sette.common.descriptors.eclipse.EclipseProject;
import hu.bme.mit.sette.common.descriptors.java.JavaClassWithMain;
import hu.bme.mit.sette.common.exceptions.SetteException;
import hu.bme.mit.sette.common.model.snippet.Snippet;
import hu.bme.mit.sette.common.model.snippet.SnippetContainer;
import hu.bme.mit.sette.common.model.snippet.SnippetProject;
import hu.bme.mit.sette.common.tasks.RunnerProjectGenerator;
import hu.bme.mit.sette.common.util.JavaFileUtils;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;

public class SpfGenerator extends RunnerProjectGenerator<SpfTool> {
    public SpfGenerator(SnippetProject snippetProject, File outputDirectory, SpfTool tool) {
        super(snippetProject, outputDirectory, tool);
    }

    @Override
    protected void afterPrepareRunnerProject(EclipseProject eclipseProject) {
        addGeneratedDirectoryToProject();
    }

    @Override
    protected void afterWriteRunnerProject(EclipseProject eclipseProject) throws IOException, SetteException {
        createGeneratedFiles();

        File buildXml = new File(getRunnerProjectSettings().getBaseDirectory(), "build.xml");
        FileUtils.copyFile(getTool().getDefaultBuildXml(), buildXml);
    }

    private void createGeneratedFiles() throws IOException {
        // generate main() for each snippet
        for (SnippetContainer container : getSnippetProject().getModel().getContainers()) {
            // skip container with higher java version than supported
            if (container.getRequiredJavaVersion().compareTo(getTool().getSupportedJavaVersion()) > 0) {
                // TODO error handling
                System.err.println("Skipping container: " + container.getJavaClass().getName()
                        + " (required Java version: " + container.getRequiredJavaVersion() + ")");
                continue;
            }

            for (Snippet snippet : container.getSnippets().values()) {
                Method method = snippet.getMethod();
                Class<?> javaClass = method.getDeclaringClass();
                Class<?>[] parameterTypes = method.getParameterTypes();

                // create .jpf descriptor
                JPFConfig jpfConfig = new JPFConfig();
                jpfConfig.target = javaClass.getName() + '_' + method.getName();

                String symbMethod = javaClass.getName() + '.' + method.getName() + '('
                        + StringUtils.repeat("sym", "#", parameterTypes.length) + ')';

                jpfConfig.symbolicMethod.add(symbMethod);

                jpfConfig.classpath = "build/";

                for (File libraryFile : getSnippetProject().getFiles().getLibraryFiles()) {
                    jpfConfig.classpath += ',' + getSnippetProjectSettings().getLibraryDirectoryPath() + '/'
                            + libraryFile.getName();
                }

                jpfConfig.listener = JPFConfig.SYMBOLIC_LISTENER;
                jpfConfig.symbolicDebug = JPFConfig.ON;

                jpfConfig.searchMultipleErrors = JPFConfig.TRUE;
                jpfConfig.decisionProcedure = JPFConfig.DP_CORAL;

                // generate main()
                JavaClassWithMain main = new JavaClassWithMain();
                main.setPackageName(javaClass.getPackage().getName());
                main.setClassName(javaClass.getSimpleName() + '_' + method.getName());

                main.imports().add(javaClass.getName());

                String[] parameterLiterals = new String[parameterTypes.length];

                int i = 0;
                for (Class<?> parameterType : parameterTypes) {
                    parameterLiterals[i] = SpfGenerator.getParameterLiteral(parameterType);
                    i++;
                }

                main.codeLines().add(javaClass.getSimpleName() + '.' + method.getName() + '('
                        + StringUtils.join(parameterLiterals, ", ") + ");");

                // save files
                String relativePath = JavaFileUtils.packageNameToFilename(main.getFullClassName());
                String relativePathJPF = relativePath + '.' + JPFConfig.JPF_CONFIG_EXTENSION;
                String relativePathMain = relativePath + '.' + JavaFileUtils.JAVA_SOURCE_EXTENSION;

                File targetJPFFile = new File(getRunnerProjectSettings().getGeneratedDirectory(), relativePathJPF);
                FileUtils.forceMkdir(targetJPFFile.getParentFile());
                FileUtils.write(targetJPFFile, jpfConfig.generate().toString());

                File targetMainFile = new File(getRunnerProjectSettings().getGeneratedDirectory(),
                        relativePathMain);
                FileUtils.forceMkdir(targetMainFile.getParentFile());
                FileUtils.write(targetMainFile, main.generateJavaCode().toString());
            }
        }
    }

    // TODO enhance visibility or refactor to other place
    /* private */static String getParameterLiteral(Class<?> javaClass) {
        if (javaClass.isPrimitive()) {
            javaClass = ClassUtils.primitiveToWrapper(javaClass);
        }

        if (javaClass.equals(Byte.class)) {
            return "(byte) 1";
        } else if (javaClass.equals(Short.class)) {
            return "(short) 1";
        } else if (javaClass.equals(Integer.class)) {
            return "1";
        } else if (javaClass.equals(Long.class)) {
            return "1L";
        } else if (javaClass.equals(Float.class)) {
            return "1.0f";
        } else if (javaClass.equals(Double.class)) {
            return "1.0";
        } else if (javaClass.equals(Boolean.class)) {
            return "false";
        } else if (javaClass.equals(Character.class)) {
            return "' '";
        } else {
            return "null";
        }
    }
}