/*
* 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.
*/
/*
* InputOutputPolicy_Test.java
* Creation date: Dec 18, 2006.
* By: Magnus Byne
*/
package org.openquark.cal.compiler;
import junit.extensions.TestSetup;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.openquark.cal.compiler.io.EntryPoint;
import org.openquark.cal.compiler.io.EntryPointSpec;
import org.openquark.cal.compiler.io.InputPolicy;
import org.openquark.cal.compiler.io.OutputPolicy;
import org.openquark.cal.machine.CALExecutor;
import org.openquark.cal.module.Cal.Core.CAL_Prelude;
import org.openquark.cal.runtime.CALExecutorException;
import org.openquark.cal.runtime.ExecutionContext;
import org.openquark.cal.runtime.MachineType;
import org.openquark.cal.services.BasicCALServices;
import org.openquark.cal.services.CALServicesTestUtilities;
public class InputOutputPolicy_Test extends TestCase {
/**
* A copy of CAL services for use in the test cases.
*/
private static BasicCALServices calServices;
private static ExecutionContext executionContext;
private static CALExecutor executor;
private static Compiler compiler;
/**
* Performs the setup for the test suite.
*/
private static void oneTimeSetUp() {
calServices = CALServicesTestUtilities.getCommonCALServices(MachineType.LECC, "cal.platform.test.cws");
executionContext = calServices.getWorkspaceManager().makeExecutionContextWithDefaultProperties();
executor = calServices.getWorkspaceManager().makeExecutor(executionContext);
compiler = calServices.getCompiler();
}
/**
* Performs the tear down for the test suite.
*/
private static void oneTimeTearDown() {
calServices = null;
executionContext =null;
executor = null;
compiler = null;
}
/**
* @return a test suite containing all the test cases for testing CAL source
* generation.
*/
public static Test suite() {
TestSuite suite = new TestSuite(InputOutputPolicy_Test.class);
return new TestSetup(suite) {
@Override
protected void setUp() {
oneTimeSetUp();
}
@Override
protected void tearDown() {
oneTimeTearDown();
}
};
}
/**
* @param name the name of the test
*/
public InputOutputPolicy_Test(String name) {
super(name);
}
/**
* Test running a polymorphic function with one typed input, which
* is sufficient to constrain the other types.
* @throws CALExecutorException
*/
public void testTypedInput_Test() throws CALExecutorException {
//policies can be used there.
CompilerMessageLogger messageLogger = new MessageLogger();
EntryPointSpec addSpec = EntryPointSpec.make(QualifiedName.make(CAL_Prelude.MODULE_NAME, "add"), new InputPolicy[] {
InputPolicy.INT_INPUT_POLICY,
InputPolicy.DEFAULT_INPUT_POLICY
}, OutputPolicy.DEFAULT_OUTPUT_POLICY);
EntryPoint add = compiler.getEntryPoint(addSpec, CAL_Prelude.MODULE_NAME, messageLogger);
assertNotNull(add);
Object addResult = executor.exec(add, new Object[] { new Integer(1), new Integer(2) });
assertTrue(addResult instanceof Integer);
assertEquals(new Integer(1 + 2), addResult);
}
/**
* Test running a polymorphic function with typed output,
* which is sufficient to constrain the inputs.
* @throws CALExecutorException
*/
public void testTypedOutput_Test() throws CALExecutorException {
//policies can be used there.
CompilerMessageLogger messageLogger = new MessageLogger();
EntryPointSpec addSpec = EntryPointSpec.make(QualifiedName.make(CAL_Prelude.MODULE_NAME, "add"), new InputPolicy[] {
InputPolicy.DEFAULT_INPUT_POLICY,
InputPolicy.DEFAULT_INPUT_POLICY
}, OutputPolicy.INT_OUTPUT_POLICY);
EntryPoint add = compiler.getEntryPoint(addSpec, CAL_Prelude.MODULE_NAME, messageLogger);
assertNotNull(add);
Object addResult = executor.exec(add, new Object[] { new Integer(1), new Integer(2) });
assertTrue(addResult instanceof Integer);
assertEquals(new Integer(1 + 2), addResult);
}
/**
* Test an error is returned when attempting to create entry point for
* a polymorphic function without supplying the type
*/
public void testAmbiguousError_Test() {
//policies can be used there.
CompilerMessageLogger messageLogger = new MessageLogger();
EntryPointSpec addSpec = EntryPointSpec.make(QualifiedName.make(CAL_Prelude.MODULE_NAME, "add"), new InputPolicy[] {
InputPolicy.DEFAULT_INPUT_POLICY,
InputPolicy.DEFAULT_INPUT_POLICY
}, OutputPolicy.DEFAULT_OUTPUT_POLICY);
EntryPoint add = compiler.getEntryPoint(addSpec, CAL_Prelude.MODULE_NAME, messageLogger);
assertNull(add); //the entry point should not be created as the output type is ambiguous
assert(messageLogger.getNMessages() > 0);
CompilerMessage error = messageLogger.getFirstError();
assertEquals(MessageKind.Error.AmbiguousTypeSignatureInInferredType.class, error.getMessageKind().getClass());
}
/**
* Test an error is returned when attempting to create entry point
* with un-unifiable types.
*/
public void testTypeIncompatabilityError_Test() {
//policies can be used there.
CompilerMessageLogger messageLogger = new MessageLogger();
EntryPointSpec addSpec = EntryPointSpec.make(QualifiedName.make(CAL_Prelude.MODULE_NAME, "add"), new InputPolicy[] {
InputPolicy.DOUBLE_INPUT_POLICY,
InputPolicy.DOUBLE_INPUT_POLICY
}, OutputPolicy.INT_OUTPUT_POLICY);
EntryPoint add = compiler.getEntryPoint(addSpec, CAL_Prelude.MODULE_NAME, messageLogger);
assertNull(add); //the entry point should not be created as the input/output types do not unify
assert(messageLogger.getNMessages() > 0);
CompilerMessage error = messageLogger.getFirstError();
assertEquals(MessageKind.Error.TypeErrorDuringApplication.class, error.getMessageKind().getClass());
}
/**
* Test output and input of typed CAL values
*/
public void testCALInputOutput_Test() throws CALExecutorException {
//policies can be used there.
CompilerMessageLogger messageLogger = new MessageLogger();
EntryPointSpec addSpec = EntryPointSpec.make(QualifiedName.make(CAL_Prelude.MODULE_NAME, "add"), new InputPolicy[] {
InputPolicy.DEFAULT_INPUT_POLICY,
InputPolicy.DEFAULT_INPUT_POLICY
}, OutputPolicy.makeTypedCalValueOutputPolicy(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.Int)));
EntryPoint add = compiler.getEntryPoint(addSpec, CAL_Prelude.MODULE_NAME, messageLogger);
//this should output 3 as a CAL internal value
Object addResult = executor.exec(add, new Object[] { new Integer(1), new Integer(2) });
EntryPointSpec addSpec2 = EntryPointSpec.make(QualifiedName.make(CAL_Prelude.MODULE_NAME, "add"), new InputPolicy[] {
InputPolicy.makeTypedCalValueInputPolicy(SourceModel.TypeExprDefn.TypeCons.make(CAL_Prelude.TypeConstructors.Int)),
InputPolicy.INT_INPUT_POLICY
}, OutputPolicy.INT_OUTPUT_POLICY);
EntryPoint add2 = compiler.getEntryPoint(addSpec2, CAL_Prelude.MODULE_NAME, messageLogger);
//this should output 3 as a CAL internal value
Object add2Result = executor.exec(add2, new Object[] { addResult, new Integer(2) });
assertTrue(add2Result instanceof Integer);
assertEquals(new Integer( (1 + 2) + 2), add2Result);
}
/**
* Test output and input of untyped CAL values
*/
public void testUnTypedCALInputOutput_Test() throws CALExecutorException {
//policies can be used there.
CompilerMessageLogger messageLogger = new MessageLogger();
EntryPointSpec addSpec = EntryPointSpec.make(QualifiedName.make(CAL_Prelude.MODULE_NAME, "add"), new InputPolicy[] {
InputPolicy.INT_INPUT_POLICY,
InputPolicy.DEFAULT_INPUT_POLICY
}, OutputPolicy.CAL_VALUE_OUTPUT_POLICY);
EntryPoint add = compiler.getEntryPoint(addSpec, CAL_Prelude.MODULE_NAME, messageLogger);
//this should output 3 as a CAL internal value
Object addResult = executor.exec(add, new Object[] { new Integer(1), new Integer(2) });
EntryPointSpec addSpec2 = EntryPointSpec.make(QualifiedName.make(CAL_Prelude.MODULE_NAME, "add"), new InputPolicy[] {
InputPolicy.CAL_VALUE_INPUT_POLICY,
InputPolicy.DEFAULT_INPUT_POLICY
}, OutputPolicy.INT_OUTPUT_POLICY);
EntryPoint add2 = compiler.getEntryPoint(addSpec2, CAL_Prelude.MODULE_NAME, messageLogger);
//this should add 2 to the CAL internal value representing 3
Object add2Result = executor.exec(add2, new Object[] { addResult, new Integer(2) });
assertTrue(add2Result instanceof Integer);
assertEquals(new Integer( (1 + 2) + 2), add2Result);
}
}