org.obeonetwork.m2doc.test.AbstractTemplatesTestSuite.java Source code

Java tutorial

Introduction

Here is the source code for org.obeonetwork.m2doc.test.AbstractTemplatesTestSuite.java

Source

/*******************************************************************************
 *  Copyright (c) 2016 Obeo. 
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *   
 *   Contributors:
 *       Obeo - initial API and implementation
 *  
 *******************************************************************************/
package org.obeonetwork.m2doc.test;

import com.google.common.io.Files;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.eclipse.acceleo.query.runtime.IQueryEnvironment;
import org.eclipse.acceleo.query.validation.type.IType;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.obeonetwork.m2doc.genconf.GenconfFactory;
import org.obeonetwork.m2doc.genconf.GenconfPackage;
import org.obeonetwork.m2doc.genconf.Generation;
import org.obeonetwork.m2doc.genconf.util.ConfigurationServices;
import org.obeonetwork.m2doc.generator.DocumentGenerationException;
import org.obeonetwork.m2doc.parser.DocumentParserException;
import org.obeonetwork.m2doc.parser.ValidationMessageLevel;
import org.obeonetwork.m2doc.provider.ProviderRegistry;
import org.obeonetwork.m2doc.provider.test.TestDiagramProvider;
import org.obeonetwork.m2doc.template.DocumentTemplate;
import org.obeonetwork.m2doc.util.M2DocUtils;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

/**
 * Run a folder with templates as a test suite JUnit.
 * 
 * @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
 */
@RunWith(Parameterized.class)
public abstract class AbstractTemplatesTestSuite {

    /**
     * The {@link DocumentTemplate}.
     */
    private static DocumentTemplate documentTemplate;

    /**
     * The {@link TemplateAstSerializer}.
     */
    private final TemplateAstSerializer templateAstSerializer = new TemplateAstSerializer();

    /**
     * The test folder path.
     */
    private final String testFolderPath;

    /**
     * The {@link Generation}.
     */
    private final Generation generation;

    /**
     * Variable types.
     */
    private final Map<String, Set<IType>> types;

    /**
     * The {@link IQueryEnvironment}.
     */
    private final IQueryEnvironment queryEnvironment;

    /**
     * Variables.
     */
    private final Map<String, Object> variables;

    /**
     * Constructor.
     * 
     * @param testFolder
     *            the test folder path
     * @throws IOException
     *             if the tested template can't be read
     * @throws DocumentParserException
     *             if the tested template can't be parsed
     */
    public AbstractTemplatesTestSuite(String testFolder) throws IOException, DocumentParserException {
        this.testFolderPath = testFolder;
        final File genconfFile = getGenconfFile(new File(testFolderPath));
        if (genconfFile.exists()) {
            final ResourceSet rs = getResourceSet();
            generation = getGeneration(genconfFile, rs);
        } else {
            generation = GenconfFactory.eINSTANCE.createGeneration();
        }
        final String templateFileName = getTemplateFile(new File(testFolderPath)).getAbsolutePath();
        setTemplateFileName(generation, templateFileName);
        ConfigurationServices configurationServices = new ConfigurationServices();
        queryEnvironment = configurationServices.initAcceleoEnvironment(generation);
        final URI templateURI = URI.createFileURI(templateFileName);
        documentTemplate = M2DocUtils.parse(templateURI, queryEnvironment);
        types = configurationServices.getTypes(queryEnvironment, generation);
        variables = configurationServices.createDefinitions(generation);
        // add providers variables
        variables.putAll(configurationServices.getProviderVariables(generation));
    }

    /**
     * Sets the {@link Generation#getTemplateFileName() template file name}.
     * 
     * @param gen
     *            the {@link Generation}
     * @param templateFileName
     *            the {@link Generation#getTemplateFileName() template file name}
     */
    protected void setTemplateFileName(Generation gen, final String templateFileName) {
        gen.setTemplateFileName(templateFileName);
    }

    /**
     * Registers the {@link TestDiagramProvider}.
     */
    @BeforeClass
    public static void beforeClass() {
        ProviderRegistry.INSTANCE.clear();
        ProviderRegistry.INSTANCE.registerProvider(new TestDiagramProvider());
    }

    /**
     * Closes the {@link DocumentTemplate}.
     * 
     * @throws IOException
     *             if the {@link DocumentTemplate} can't be closed
     */
    @AfterClass
    public static void afterClass() throws IOException {
        documentTemplate.close();
        ProviderRegistry.INSTANCE.clear();
    }

    /**
     * Gets the {@link Generation}.
     * 
     * @param genconfFile
     *            the {@link Generation} file
     * @param rs
     *            the {@link ResourceSet}
     * @return the {@link Generation}
     */
    protected Generation getGeneration(File genconfFile, ResourceSet rs) {
        return (Generation) rs.getResource(URI.createFileURI(genconfFile.getAbsolutePath()), true).getContents()
                .get(0);
    }

    /**
     * Gets the test folder path.
     * 
     * @return the test folder path
     */
    protected String getTestFolderPath() {
        return testFolderPath;
    }

    /**
     * Gets the {@link ResourceSet}.
     * 
     * @return the {@link ResourceSet}
     */
    protected ResourceSet getResourceSet() {
        ResourceSetImpl res = new ResourceSetImpl();

        res.getPackageRegistry().put(GenconfPackage.eNS_URI, GenconfPackage.eINSTANCE);
        res.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new XMIResourceFactoryImpl());

        return res;
    }

    /**
     * Tests the parsing by comparing a textual representation of the AST.
     * 
     * @throws IOException
     *             if the expected AST file can't be read
     * @throws FileNotFoundException
     *             if the expected AST file can't be found
     */
    @Test
    public void parsing() throws FileNotFoundException, IOException {
        final File expectedASTFile = getExpectedASTFile(new File(testFolderPath));
        final String actualAst = templateAstSerializer.serialize(documentTemplate);
        if (!expectedASTFile.exists()) {
            final File actualASTFile = getActualASTFile(new File(testFolderPath));
            if (!actualASTFile.exists()) {
                actualASTFile.createNewFile();
            }
            try (FileOutputStream stream = new FileOutputStream(actualASTFile);) {
                setContent(stream, "UTF-8", actualAst);
            }
            fail(expectedASTFile.getAbsolutePath() + " doesn't exists.");
        }
        try (FileInputStream stream = new FileInputStream(expectedASTFile)) {
            final String expectedAst = getContent(stream, "UTF-8");
            assertEquals(expectedAst, actualAst);
        }
    }

    /**
     * Tests the parsing by comparing the validated template.
     * 
     * @throws IOException
     *             if the validation template can't be generated
     * @throws DocumentGenerationException
     *             if the validation template can't be generated
     */
    @Test
    public void validation() throws IOException, DocumentGenerationException {
        final ValidationMessageLevel validationLevel = M2DocUtils.validate(documentTemplate, queryEnvironment,
                types);

        final File expectedValidationFile = getExpectedValidatedFile(new File(testFolderPath));
        final File tempFile;
        if (expectedValidationFile.exists()) {
            tempFile = File.createTempFile(expectedValidationFile.getAbsolutePath(), "validation-test.docx");
            if (validationLevel != ValidationMessageLevel.OK) {
                M2DocUtils.serializeValidatedDocumentTemplate(documentTemplate,
                        URI.createFileURI(tempFile.getAbsolutePath()));
            }
        } else {
            tempFile = getActualValidatedFile(new File(testFolderPath));
            tempFile.createNewFile();
            if (validationLevel != ValidationMessageLevel.OK) {
                M2DocUtils.serializeValidatedDocumentTemplate(documentTemplate,
                        URI.createFileURI(tempFile.getAbsolutePath()));
            }
            fail(expectedValidationFile.getAbsolutePath() + " doesn't exists.");
        }

        if (tempFile.length() != 0) {
            M2DocTestUtils.assertDocx(expectedValidationFile.getAbsolutePath(), tempFile.getAbsolutePath());
        } else {
            assertEquals(ValidationMessageLevel.OK, validationLevel);
            assertTrue(expectedValidationFile.exists());
            assertEquals(0, expectedValidationFile.length());
        }

        tempFile.delete();
    }

    /**
     * Tests the parsing by comparing the result of the generation.
     * 
     * @throws Exception
     *             if the generation fails
     */
    @Test
    public void generation() throws Exception {
        final File expectedGeneratedFile = getExpectedGeneratedFile(new File(testFolderPath));
        final File templateFile = getTemplateFile(new File(testFolderPath));
        final File userContentFile = getUserContentFile(new File(testFolderPath));

        File outputFile = null;
        if (expectedGeneratedFile.exists()) {
            outputFile = File.createTempFile(expectedGeneratedFile.getAbsolutePath(), "generated-test");
        } else {
            outputFile = getActualGeneratedFile(new File(testFolderPath));
            if (userContentFile.exists()) {
                Files.copy(userContentFile, outputFile);
            }
            generateTemplate(templateFile, outputFile);
            fail(expectedGeneratedFile.getAbsoluteFile() + " doesn't exists.");
        }

        try (FileInputStream is = new FileInputStream(templateFile)) {
            try (OPCPackage oPackage = OPCPackage.open(is)) {
                try (XWPFDocument document = new XWPFDocument(oPackage)) {
                    if (userContentFile.exists()) {
                        Files.copy(userContentFile, outputFile);
                    }
                    generateTemplate(templateFile, outputFile);
                    M2DocTestUtils.assertDocx(expectedGeneratedFile.getAbsolutePath(),
                            outputFile.getAbsolutePath());
                }
            }
        } finally {
            if (outputFile != null) {
                outputFile.delete();
            }
        }
    }

    /**
     * Generates the given template to the given output file.
     * 
     * @param templateFile
     *            the template .docx
     * @param outputFile
     *            the output file .docx
     * @throws DocumentGenerationException
     *             if the document can't be generated
     * @throws IOException
     *             if the input ou output files can't be read/write
     * @throws DocumentParserException
     *             if the template can't be parsed
     */
    private void generateTemplate(final File templateFile, File outputFile)
            throws DocumentGenerationException, IOException, DocumentParserException {
        String outputPath = outputFile.getAbsolutePath();
        M2DocUtils.generate(documentTemplate, queryEnvironment, variables, URI.createFileURI(outputPath));
    }

    /**
     * Gets the template file from the test folder path.
     * 
     * @param testFolder
     *            the test folder path
     * @return the template file from the test folder path
     */
    protected final File getTemplateFile(File testFolder) {
        return getTemplateFileInternal(testFolder);
    }

    /**
     * Gets the expected AST file from the test folder path.
     * 
     * @param testFolder
     *            the test folder path
     * @return the template file from the test folder path
     */
    protected File getExpectedASTFile(File testFolder) {
        return new File(testFolder + File.separator + testFolder.getName() + "-expected-ast.txt");
    }

    /**
     * Gets the actual AST file from the test folder path.
     * 
     * @param testFolder
     *            the test folder path
     * @return the actual file from the test folder path
     */
    protected File getActualASTFile(File testFolder) {
        return new File(testFolder + File.separator + testFolder.getName() + "-actual-ast.txt");
    }

    /**
     * Gets the expected validated template file from the test folder path.
     * 
     * @param testFolder
     *            the test folder path
     * @return the expected template file from the test folder path
     */
    protected File getExpectedValidatedFile(File testFolder) {
        return new File(testFolder + File.separator + testFolder.getName() + "-expected-validation.docx");
    }

    /**
     * Gets the actual validated template file from the test folder path.
     * 
     * @param testFolder
     *            the test folder path
     * @return the actual template file from the test folder path
     */
    protected File getActualValidatedFile(File testFolder) {
        return new File(testFolder + File.separator + testFolder.getName() + "-actual-validation.docx");
    }

    /**
     * Gets the expected generated file from the test folder path.
     * 
     * @param testFolder
     *            the test folder path
     * @return the expected template file from the test folder path
     */
    protected File getExpectedGeneratedFile(File testFolder) {
        return new File(testFolder + File.separator + testFolder.getName() + "-expected-generation.docx");
    }

    /**
     * Gets the actual generated file from the test folder path.
     * 
     * @param testFolder
     *            the test folder path
     * @return the actual generated file from the test folder path
     */
    protected File getActualGeneratedFile(File testFolder) {
        return new File(testFolder + File.separator + testFolder.getName() + "-actual-generation.docx");
    }

    /**
     * Gets the user content file from the test folder path.
     * 
     * @param testFolder
     *            the test folder path
     * @return the user content file from the test folder path
     */
    protected File getUserContentFile(File testFolder) {
        return new File(testFolder + File.separator + testFolder.getName() + "-userContent.docx");
    }

    /**
     * Gets the genconf file from the test folder path.
     * 
     * @param testFolder
     *            the test folder path
     * @return the genconf file from the test folder path
     */
    protected File getGenconfFile(File testFolder) {
        return new File(testFolder + File.separator + testFolder.getName() + ".genconf");
    }

    /**
     * Gets the template file from the test folder path.
     * 
     * @param testFolder
     *            the test folder path
     * @return the template file from the test folder path
     */
    private static File getTemplateFileInternal(File testFolder) {
        return new File(testFolder + File.separator + testFolder.getName() + "-template.docx");
    }

    /**
     * Gets the {@link Collection} of test folders from the given folder path.
     * 
     * @param folderPath
     *            the folder path
     * @return the {@link Collection} of test folders from the given folder path
     */
    public static Collection<Object[]> retrieveTestFolders(String folderPath) {
        Collection<Object[]> parameters = new ArrayList<Object[]>();

        File folder = new File(folderPath);
        final File[] children = folder.listFiles(new FileFilter() {

            @Override
            public boolean accept(File pathname) {
                final boolean res;

                if (pathname.isDirectory() && pathname.canRead()) {
                    res = getTemplateFileInternal(pathname).exists();
                } else {
                    res = false;
                }

                return res;
            }

        });
        Arrays.sort(children);
        for (File child : children) {
            parameters.add(new Object[] { child.getPath() });
        }

        return parameters;
    }

    /**
     * Gets the content of the given {@link InputStream}.
     * 
     * @param stream
     *            the {@link InputStream}
     * @param charsetName
     *            The name of a supported {@link java.nio.charset.Charset </code>charset<code>}
     * @return a {@link CharSequence} of the content of the given {@link InputStream}
     * @throws IOException
     *             if the {@link InputStream} can't be read
     */
    public static String getContent(InputStream stream, String charsetName) throws IOException {
        final int len = 8192;
        StringBuilder res = new StringBuilder(len);
        if (len != 0) {
            try (InputStreamReader input = new InputStreamReader(new BufferedInputStream(stream), charsetName)) {
                char[] buffer = new char[len];
                int length = input.read(buffer);
                while (length != -1) {
                    res.append(buffer, 0, length);
                    length = input.read(buffer);
                }
            }
        }
        return res.toString();
    }

    /**
     * Sets the given content to the given {@link OutputStream}.
     * 
     * @param stream
     *            the {@link OutputStream}
     * @param charsetName
     *            the charset name
     * @param content
     *            the content to write
     * @throws UnsupportedEncodingException
     *             if the given charset is not supported
     * @throws IOException
     *             if the given stream can't be written to
     */
    public static void setContent(OutputStream stream, String charsetName, String content)
            throws UnsupportedEncodingException, IOException {
        stream.write(content.getBytes(charsetName));
        stream.flush();
    }

}