Package org.openquark.cal.compiler

Source Code of org.openquark.cal.compiler.CompilerTestUtilities

/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of Business Objects nor the names of its contributors
*       may be used to endorse or promote products derived from this software
*       without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/


/*
* CompilerTestUtilities.java
* Creation date: Mar 2, 2005.
* By: Joseph Wong
*/
package org.openquark.cal.compiler;

import java.io.StringReader;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import junit.framework.Assert;

import org.openquark.cal.compiler.CompilerMessage.AbortCompilation;
import org.openquark.cal.module.Cal.Core.CAL_Prelude;
import org.openquark.cal.services.BasicCALServices;
import org.openquark.cal.services.Status;
import org.openquark.cal.services.StringModuleSourceDefinition;
import org.openquark.cal.services.WorkspaceManager;
import org.openquark.util.General;


/**
* A set of helper methods for use in JUnit test cases that need to access functionalities
* provided by package-scoped classes/methods in the CAL compiler package.
*
* @author Joseph Wong
*/
public class CompilerTestUtilities {
   
   
    /**
     * Helper method to convert a string containing a CAL module definition
     * into the corresponding parse tree. Exceptions thrown by the
     * compiler are caught by this method, and it returns null when the
     * parsing fails.
     *
     * @param moduleDefnStr
     *            the string containing the CAL module definition
     * @return the corresponding parse tree, or null if the compiler
     *         cannot parse the supplied argument as a module definition
     */
    static ParseTreeNode parseModuleDefnIntoParseTreeNode(String moduleDefnStr) {
        return parseModuleDefnIntoParseTreeNode(moduleDefnStr, null);
    }
    /**
     * Helper method to convert a string containing a CAL module definition
     * into the corresponding parse tree. Exceptions thrown by the
     * compiler are caught by this method, and it returns null when the
     * parsing fails.
     *
     * @param moduleDefnStr
     *            the string containing the CAL module definition
     * @param embellishments - collection in which to store source embellishments
     *      encounter when parsing source.
     * @return the corresponding parse tree, or null if the compiler
     *         cannot parse the supplied argument as a module definition
     */
    static ParseTreeNode parseModuleDefnIntoParseTreeNode(String moduleDefnStr, Collection<SourceEmbellishment> embellishments) {
       
        CALCompiler compiler = new CALCompiler();
       
        // Use a compiler-specific logger, so that fatal errors abort compilation.
        CompilerMessageLogger compileLogger = new MessageLogger(true);
        compiler.setCompilerMessageLogger(compileLogger);

        CALParser parser = freshParser(compiler, new StringReader(moduleDefnStr), embellishments);
        CALTreeParser treeParser = new CALTreeParser(compiler);
        try {
            parser.module();
            ParseTreeNode moduleDefnNode = (ParseTreeNode)parser.getAST();
            treeParser.module(moduleDefnNode);
           
            return moduleDefnNode;
           
        } catch (antlr.RecognitionException e) {          
            // Recognition (syntax) error
        } catch (antlr.TokenStreamException e) {
            // Bad token stream.  Maybe a bad token (eg. a stray "$" sign)
        } catch (AbortCompilation e) {
            //compilation aborted   
        } catch (Exception e) {
            // Major failure - internal coding error
        }
       
        return null;
    }
       
    /**
     * Construct a new parser state from the given reader. The returned parser
     * will have its lexer and stream selector set, and will be configured for
     * ASTNodes of type ParseTreeNode. Note that tree nodes created by this
     * parser will not have any source name (filename) info.
     *
     * @param compiler
     *            The compiler. This will be used for message logging and for
     *            parser access to its stream selector.
     * @param reader
     *            the reader from which to parse.
     * @return CALParser a new parser configured for the given args.
     *
     * (see CALTypeChecker.freshParser(CALCompiler, java.io.Reader) )
     */
    private static final CALParser freshParser(CALCompiler compiler, java.io.Reader reader, Collection<SourceEmbellishment> embellishments) {
   
        // Make a multiplexed lexer
        CALMultiplexedLexer lexer = new CALMultiplexedLexer(compiler, reader, embellishments);
       
        // Create a parser, it gets its tokens from the multiplexed lexer
        CALParser parser = new CALParser(compiler, lexer);
   
        String treeNodeClassName = ParseTreeNode.class.getName();
        parser.setASTNodeClass(treeNodeClassName);
   
        return parser;
    }
   
    /**
     * Returns whether the message kind represents an internal coding error.
     * @param messageKind the message kind to check
     * @return true iff the message kind represents an internal coding error.
     */
    public static boolean isInternalCodingError(MessageKind messageKind) {
        return messageKind instanceof MessageKind.Fatal.InternalCodingError;
    }
   
    /**
     * Get the name of a new module which doesn't exist in the program
     * @param calServices the cal services object on which to generate the module name.
     * @return the name of a module which doesn't exist in the program.
     */
    public static ModuleName getNewModuleName(BasicCALServices calServices) {
        WorkspaceManager workspaceManager = calServices.getWorkspaceManager();
        Set<ModuleName> moduleNames = new HashSet<ModuleName>(Arrays.asList(workspaceManager.getModuleNamesInProgram()));
       
        String baseName = "CompilerTestModule";
        ModuleName moduleName = ModuleName.make(baseName);
        int index = 1;
        while (moduleNames.contains(moduleName)){
            moduleName = ModuleName.make(baseName + "_" + index);
            index++;
        }
        return moduleName;
    }

    /**
     * Check that a given set of outer defns gives a compile error when compiled to a new module.
     * @param outerDefnText the text of the outer defns.
     * @param expectedErrorClass the class of the expected error.
     * @param calServices the CAL services object in use in the test case.
     */
    static void checkDefnForExpectedError(String outerDefnText, Class<? extends MessageKind.Error> expectedErrorClass, BasicCALServices calServices) {
        checkDefnForExpectedError(new String[]{outerDefnText}, expectedErrorClass, calServices);
    }

    /**
     * Check that a given set of outer defns gives a compile error when compiled to a new module.
     * @param outerDefnTextLines the lines of text of the outer defns.
     * @param expectedErrorClass the class of the expected error.
     * @param calServices the CAL services object in use in the test case.
     */
    static void checkDefnForExpectedError(String[] outerDefnTextLines, Class<? extends MessageKind.Error> expectedErrorClass, BasicCALServices calServices) {
        ModuleName moduleName = getNewModuleName(calServices);
        checkDefnForExpectedError(moduleName, outerDefnTextLines, expectedErrorClass, calServices);
    }
   
    /**
     * Check that a given set of outer defns gives a compile error when compiled to a module.
     * @param moduleName the name of the module.
     * @param outerDefnText the text of the outer defns.
     * @param expectedErrorClass the class of the expected error.
     * @param calServices the CAL services object in use in the test case.
     */
    static void checkDefnForExpectedError(ModuleName moduleName, String outerDefnText, Class<? extends MessageKind.Error> expectedErrorClass, BasicCALServices calServices) {
        checkDefnForExpectedError(moduleName, new String[]{outerDefnText}, expectedErrorClass, calServices);
    }

    /**
     * Check that a given set of outer defns gives a compile error when compiled to a module.
     * @param moduleName the name of the module.
     * @param outerDefnTextLines the lines of text of the outer defns.
     * @param expectedErrorClass the class of the expected error.
     * @param calServices the CAL services object in use in the test case.
     */
    static void checkDefnForExpectedError(ModuleName moduleName, String[] outerDefnTextLines, Class<? extends MessageKind.Error> expectedErrorClass, BasicCALServices calServices) {
        String outerDefnText = concatLines(outerDefnTextLines);
        CompilerMessageLogger logger = compileAndRemoveModule(moduleName, outerDefnText, calServices);
       
        // Check that we got an error message of the expected type.
        List<CompilerMessage> messages = logger.getCompilerMessages(CompilerMessage.Severity.ERROR);
        Assert.assertTrue("No errors logged.", !messages.isEmpty());

        Set<Class<? extends MessageKind>> messageKindClasses = new HashSet<Class<? extends MessageKind>>();
        for (int i = 0, n = messages.size(); i < n; i++) {
            CompilerMessage message = messages.get(i);
            messageKindClasses.add(message.getMessageKind().getClass());
        }
       
        Assert.assertTrue("expected: <" + expectedErrorClass + "> but was: <" + messageKindClasses + ">", messageKindClasses.contains(expectedErrorClass));
    }

    /**
     * Compile outer defn and return the messages
     * @param moduleName
     * @param outerDefnTextLines
     * @param calServices
     * @return list of compiler messages
     */
    static List<CompilerMessage> compileAndGetMessages(ModuleName moduleName,
                                                       String[] outerDefnTextLines,
                                                       BasicCALServices calServices) {
        String outerDefnText = concatLines(outerDefnTextLines);
        CompilerMessageLogger logger = compileAndRemoveModule(moduleName, outerDefnText, calServices);
       
        // return the error messages
        return logger.getCompilerMessages(CompilerMessage.Severity.ERROR);
    }
       
   
    /**
     * Check that a given set of outer defns gives a compile warning when compiled to a new module.
     * @param outerDefnText the text of the outer defns.
     * @param expectedWarningClass the class of the expected warning.
     * @param calServices the CAL services object in use in the test case.
     */
    static void checkDefnForExpectedWarning(String outerDefnText, Class<? extends MessageKind.Warning> expectedWarningClass, BasicCALServices calServices) {
        checkDefnForExpectedWarning(new String[]{outerDefnText}, expectedWarningClass, calServices);
    }

    /**
     * Check that a given set of outer defns gives a compile warning when compiled to a new module.
     * @param outerDefnTextLines the lines of text of the outer defns.
     * @param expectedWarningClass the class of the expected warning.
     * @param calServices the CAL services object in use in the test case.
     */
    static void checkDefnForExpectedWarning(String[] outerDefnTextLines, Class<? extends MessageKind.Warning> expectedWarningClass, BasicCALServices calServices) {
        final ModuleName moduleName = getNewModuleName(calServices);
        checkDefnForExpectedWarning(moduleName, outerDefnTextLines, expectedWarningClass, calServices);
    }
   
    /**
     * Check that a given set of outer defns gives a compile warning when compiled to a module.
     * @param moduleName the name of the module.
     * @param outerDefnText the text of the outer defns.
     * @param expectedWarningClass the class of the expected warning.
     * @param calServices the CAL services object in use in the test case.
     */
    static void checkDefnForExpectedWarning(ModuleName moduleName, String outerDefnText, Class<? extends MessageKind.Warning> expectedWarningClass, BasicCALServices calServices) {
        checkDefnForExpectedWarning(moduleName, new String[]{outerDefnText}, expectedWarningClass, calServices);
    }

    /**
     * Check that a given set of outer defns gives a compile warning when compiled to a module.
     * @param moduleName the name of the module.
     * @param outerDefnTextLines the lines of text of the outer defns.
     * @param expectedWarningClass the class of the expected warning.
     * @param calServices the CAL services object in use in the test case.
     */
    static void checkDefnForExpectedWarning(ModuleName moduleName, String[] outerDefnTextLines, Class<? extends MessageKind.Warning> expectedWarningClass, BasicCALServices calServices) {
        final String outerDefnText = concatLines(outerDefnTextLines);
        final CompilerMessageLogger logger = compileAndRemoveModule(moduleName, outerDefnText, calServices);
       
        // Check that we got an warning message of the expected type.
        final List<CompilerMessage> messages = logger.getCompilerMessages();
       
        CompilerMessage warning = null;
        for (int i = 0, n = messages.size(); i < n; i++) {
            CompilerMessage message = messages.get(i);
            if (message.getSeverity() == CompilerMessage.Severity.WARNING) {
                warning = message;
                break;
            }
        }
       
        Assert.assertEquals("Unexpected errors logged.", Collections.EMPTY_LIST, logger.getCompilerMessages(CompilerMessage.Severity.ERROR));
        Assert.assertTrue("No warnings logged.", warning != null);
        Assert.assertEquals(expectedWarningClass, warning.getMessageKind().getClass());
    }

    /**
     * Check that a given set of outer defns gives a compile warning when compiled to a new module.
     * @param outerDefnText the text of the outer defns.
     * @param expectedWarningClass the class of the expected warning.
     * @param nWarningsExpected the number of warnings of that class to be expected.
     * @param calServices the CAL services object in use in the test case.
     */
    static void checkDefnForMultipleExpectedWarnings(String outerDefnText, Class<? extends MessageKind.Warning> expectedWarningClass, int nWarningsExpected, BasicCALServices calServices) {
        final ModuleName moduleName = getNewModuleName(calServices);
        final CompilerMessageLogger logger = compileAndRemoveModule(moduleName, outerDefnText, calServices);
       
        // Check that we got an warning message of the expected type.
        final List<CompilerMessage> messages = logger.getCompilerMessages();
       
        Assert.assertEquals("Unexpected errors logged.", Collections.EMPTY_LIST, logger.getCompilerMessages(CompilerMessage.Severity.ERROR));
       
        int nWarningsEncountered = 0;
        for (int i = 0, n = messages.size(); i < n; i++) {
            CompilerMessage message = messages.get(i);
            if (message.getSeverity() == CompilerMessage.Severity.WARNING) {
                if (message.getMessageKind().getClass().equals(expectedWarningClass)) {
                    nWarningsEncountered++;
                } else {
                    Assert.assertEquals("Unexpected warning class", expectedWarningClass, message.getMessageKind().getClass());
                }
            }
        }
       
        Assert.assertEquals("Mismatch between number of warnings expected and number of warnings encountered", nWarningsExpected, nWarningsEncountered);
    }
       
    /**
     * Asserts that two strings are equal after converting them both to
     * the platform line feed representation
     * @param expected
     * @param actual
     */
    static void assertEqualsCanonicalLineFeed(String expected, String actual) {
        Assert.assertEquals(General.toPlatformLineSeparators(expected), General.toPlatformLineSeparators(actual));
    }
   
    /**
     * Concatenate an array of strings into lines of text delimited with newlines.
     * @param lines the string to consider as lines of text.
     * @return the concatenated string.
     */
    private static String concatLines(String[] lines) {
        StringBuilder sb = new StringBuilder();
        for (final String line : lines) {
            sb.append(line).append('\n');
        }
        return sb.toString();
    }
   
    /**
     * Compile a new module containing a module definition, an import statement for the Prelude, and the given text.
     * @param moduleName the name of the module.
     * @param outerDefnText the text of the definitions in the module.
     * @param calServices the CAL services object in use in the test case.
     * @return a logger which logged the results of the compile.
     */
    private static CompilerMessageLogger compileAndRemoveModule(ModuleName moduleName, String outerDefnText, BasicCALServices calServices) {
        String sourceDefString = "module " + moduleName + ";\n";
        sourceDefString += "import " + CAL_Prelude.MODULE_NAME + ";\n";
        sourceDefString += outerDefnText;
       
        ModuleSourceDefinition sourceDef = new StringModuleSourceDefinition(moduleName, sourceDefString);
       
        // Get the workspace manager and the logger.
        WorkspaceManager workspaceManager = calServices.getWorkspaceManager();
        CompilerMessageLogger logger = new MessageLogger();

        // Compile the module.
        workspaceManager.makeModule(sourceDef, logger);

        // Remove the module.
        calServices.getWorkspaceManager().removeModule(moduleName, new Status("Remove module status."));

        return logger;
    }
   

}
TOP

Related Classes of org.openquark.cal.compiler.CompilerTestUtilities

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.