/******************************************************************************* * Copyright (c) 2006, 2009 IBM Corporation and others. * 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: * IBM - Initial API and implementation *******************************************************************************/ package org.eclipse.ocl.uml.tests; import java.util.List; import org.eclipse.ocl.helper.Choice; import org.eclipse.ocl.helper.ChoiceKind; import org.eclipse.ocl.helper.ConstraintKind; /** * Tests for message expressions. * * @author Christian W. Damus (cdamus) */ @SuppressWarnings("nls") public class MessagesTest extends AbstractTestSuite { /** * Tests the parsing of the hasSent ("^") expression for operations. */ public void test_hasSent_operation() { helper.setOperationContext(fruit, fruit_ripen); try { // test query operation calls without any arguments helper.createPostcondition("self^preferredColor()"); // test non-query operation calls without any arguments helper.createPostcondition("self ^ newFruit()"); // test operation calls with one argument. Incidentally put a more // interesting expression as the target helper.createPostcondition( "Apple.allInstances()->any(true) ^ripen(Color::yellow)"); // test operation calls with multiple arguments helper.createPostcondition( "Fruit.allInstances()->forAll(f | self^setColor(f, Color::red))"); // test operation signature conformance matching helper.createPostcondition( "Apple.allInstances()->forAll(a | self^setColor(a, Color::red))"); // test operation signature conformance matching with null object type helper.createPostcondition( "Apple.allInstances()->forAll(a | self^setColor(null, Color::red))"); // test operation signature conformance matching with null data type helper.createPostcondition( "Apple.allInstances()->forAll(a | self^setColor(a, null))"); } catch (Exception e) { fail("Failed to parse: " + e.getLocalizedMessage()); } } /** * Tests the validation of the hasSent ("^") expression for operations. */ public void test_hasSent_operation_validation() { helper.setOperationContext(fruit, fruit_ripen); try { // non-existent operation helper.createPostcondition("self^label('foo')"); fail("Should have failed to parse unknown operation"); } catch (Exception e) { // success System.out.println("Got expected error: " + e.getLocalizedMessage()); } try { // non-conformant argument helper.createPostcondition("self^setColor(self, 'red')"); fail("Should have failed to parse non-conformant arg"); } catch (Exception e) { // success System.out.println("Got expected error: " + e.getLocalizedMessage()); } } /** * Tests parsing of the hasSent ("^") expression with unspecified value * expressions for operations. */ public void test_hasSent_operation_unspecifiedValue() { helper.setOperationContext(fruit, fruit_ripen); try { helper.createPostcondition( "Apple.allInstances()->any(true)^ripen(? : Color)"); helper.createPostcondition( "Fruit.allInstances()->forAll(f | self^setColor(? : Fruit, ? : Color))"); helper.createPostcondition( "Apple.allInstances()->any(true)^ripen(?)"); helper.createPostcondition( "Fruit.allInstances()->forAll(f | self^setColor(?, ?))"); } catch (Exception e) { fail("Failed to parse: " + e.getLocalizedMessage()); } } /** * Tests validation of the hasSent ("^") expression with unspecified value * expressions for operations. */ public void test_hasSent_operation_unspecifiedValue_validation() { helper.setOperationContext(fruit, fruit_ripen); try { // non-existent operation helper.createPostcondition("self^label(?)"); fail("Should have failed to parse unknown operation"); } catch (Exception e) { // success System.out.println("Got expected error: " + e.getLocalizedMessage()); } try { // non-conformant argument helper.createPostcondition("self^setColor(self, ? : String)"); fail("Should have failed to parse non-conformant arg"); } catch (Exception e) { // success System.out.println("Got expected error: " + e.getLocalizedMessage()); } } /** * Tests the parsing of the sentMessages ("^^") expression for operations. */ public void test_sentMessages_operation() { helper.setOperationContext(fruit, fruit_ripen); try { // test query operation calls without any arguments helper.createPostcondition( "self^^preferredColor()->notEmpty()"); // test non-query operation calls without any arguments helper.createPostcondition("self^^newFruit()->first().oclIsKindOf(OclMessage)"); // test operation calls with one argument. Incidentally put a more // interesting expression as the target helper.createPostcondition( "Apple.allInstances()->any(true)^^ripen(Color::yellow)->notEmpty()"); // test operation calls with multiple arguments helper.createPostcondition( "Fruit.allInstances()->collect(f | self^^setColor(f, Color::red))->notEmpty()"); // test operation signature conformance matching helper.createPostcondition( "Apple.allInstances()->collect(a | self^^setColor(a, Color::red))->notEmpty()"); // test operation signature conformance matching with null object type helper.createPostcondition( "Apple.allInstances()->collect(a | self^^setColor(null, Color::red))->notEmpty()"); // test operation signature conformance matching with null data type helper.createPostcondition( "Apple.allInstances()->collect(a | self^^setColor(a, null))->notEmpty()"); } catch (Exception e) { fail("Failed to parse: " + e.getLocalizedMessage()); } } /** * Tests the parsing of OclMessage expressions for operations. */ public void test_message_access_operation() { helper.setOperationContext(fruit, fruit_ripen); try { // test type conformance helper.createPostcondition( "let msgs : Sequence(OclMessage) = self^^preferredColor() in " + "msgs->forAll(m | m.hasReturned() and m.isOperationCall() and not m.isSignalSent())"); // test non-query operation calls without any arguments helper.createPostcondition("self^^newFruit()->first().oclIsKindOf(OclMessage)"); // test operation calls with one argument. Incidentally put a more // interesting expression as the target helper.createPostcondition( "Apple.allInstances()->any(true)^^ripen(Color::yellow)->notEmpty()"); // types of the OclMessage properties are determined by the actual // operation type, not by the MessageExp arguments helper.createPostcondition( "let msgs : Collection(OclMessage) = Fruit.allInstances()->collect(f | self^^setColor(?, ?)) in " + "msgs->forAll(m | m.fruit.color = Color::black implies m.newColor = Color::black)"); // return values helper.createPostcondition( "let msgs : Collection(OclMessage) = Fruit.allInstances()->collect(f | self^^newFruit()) in " + "msgs->forAll(m | m.hasReturned() implies m.result().color = Color::green)"); } catch (Exception e) { fail("Failed to parse: " + e.getLocalizedMessage()); } } /** * Tests the validation of the setMessages ("^^") expression for operations. */ public void test_sentMessages_operation_validation() { helper.setOperationContext(fruit, fruit_ripen); try { // non-existent operation helper.createPostcondition("self^^label('foo')->notEmpty()"); fail("Should have failed to parse unknown operation"); } catch (Exception e) { // success System.out.println("Got expected error: " + e.getLocalizedMessage()); } try { // non-conformant argument helper.createPostcondition("self^^setColor(self, 'red')->notEmpty()"); fail("Should have failed to parse non-conformant arg"); } catch (Exception e) { // success System.out.println("Got expected error: " + e.getLocalizedMessage()); } } /** * Tests the parsing of the hasSent ("^") expression for signals. */ public void test_hasSent_signal() { helper.setOperationContext(apple, fruit_ripen); try { helper.createPostcondition("self^Drop(3, self.stem)"); helper.createPostcondition("self ^ Drop(? : Real, ? : Stem)"); helper.createPostcondition("self ^Drop(? : Integer, ?)"); helper.createPostcondition("self^Drop(?, ?)"); helper.createPostcondition( "Apple.allInstances()->any(true)^Drop(3, stem)"); helper.createPostcondition( "Apple.allInstances()->exists(a | a^Drop(3, stem))"); helper.createPostcondition( "Fruit.allInstances()->forAll(f | f^Drop(?, ?) implies self^Drop(?, ?))"); } catch (Exception e) { fail("Failed to parse: " + e.getLocalizedMessage()); } } /** * Tests the validation of the hasSent ("^") expression for signals. */ public void test_hasSent_signal_validation() { helper.setOperationContext(fruit, fruit_ripen); try { // non-existent signal helper.createPostcondition("self^Rot(3, stem)"); fail("Should have failed to parse unknown signal"); } catch (Exception e) { // success System.out.println("Got expected error: " + e.getLocalizedMessage()); } try { // non-conformant argument helper.createPostcondition("self^Drop('red', ?)"); fail("Should have failed to parse non-conformant arg"); } catch (Exception e) { // success System.out.println("Got expected error: " + e.getLocalizedMessage()); } } /** * Tests the parsing of the sentMessages ("^^") expression for signals. */ public void test_sentMessages_signal() { helper.setOperationContext(fruit, fruit_ripen); try { helper.createPostcondition( "self^^Drop(3, self.oclAsType(Apple).stem)->notEmpty()"); helper.createPostcondition("self^^Drop(?, ?)->first().oclIsKindOf(OclMessage)"); helper.createPostcondition( "Apple.allInstances()->any(true)^^Drop(3, ?)->notEmpty()"); helper.createPostcondition( "Apple.allInstances()->collect(a | self^^Drop(null, ? : Stem))->notEmpty()"); helper.createPostcondition( "Apple.allInstances()->collect(a | self^^Drop(3, null))->notEmpty()"); } catch (Exception e) { fail("Failed to parse: " + e.getLocalizedMessage()); } } /** * Tests the parsing of OclMessage expressions for signals. */ public void test_message_access_signal() { helper.setOperationContext(apple, fruit_ripen); try { helper.createPostcondition( "let msgs : Sequence(OclMessage) = self^^Drop(?, ?) in " + "msgs->forAll(m | m.isSignalSent() and not m.isOperationCall())"); helper.createPostcondition("self^^Drop(?, ?)->first().oclIsKindOf(OclMessage)"); helper.createPostcondition( "let msgs : Collection(OclMessage) = Fruit.allInstances()->collect(f | self^^Drop(?, ?)) in " + "msgs->forAll(m | m.delay > 0 and stem <> self.stem)"); } catch (Exception e) { fail("Failed to parse: " + e.getLocalizedMessage()); } } /** * Tests the validation of the setMessages ("^^") expression for signals. */ public void test_sentMessages_signal_validation() { helper.setOperationContext(fruit, fruit_ripen); try { // non-existent signal helper.createPostcondition("self^^Rot('now')->notEmpty()"); fail("Should have failed to parse unknown signal"); } catch (Exception e) { // success System.out.println("Got expected error: " + e.getLocalizedMessage()); } try { // non-conformant argument helper.createPostcondition("self^^Drop(self, ?)->notEmpty()"); fail("Should have failed to parse non-conformant arg"); } catch (Exception e) { // success System.out.println("Got expected error: " + e.getLocalizedMessage()); } } /** * Tests the presentation of operation call choices. */ public void test_contentAssist_operations() { helper.setOperationContext(fruit, fruit_ripen); try { List<Choice> choices = helper.getSyntaxHelp( ConstraintKind.POSTCONDITION, "self^"); assertNotNull(choices); assertChoice(choices, ChoiceKind.OPERATION, "newFruit"); assertChoice(choices, ChoiceKind.OPERATION, "setColor"); assertNotChoice(choices, ChoiceKind.OPERATION, "oclIsKindOf"); choices = helper.getSyntaxHelp( ConstraintKind.POSTCONDITION, "self^^"); assertNotNull(choices); assertChoice(choices, ChoiceKind.OPERATION, "newFruit"); assertChoice(choices, ChoiceKind.OPERATION, "setColor"); assertNotChoice(choices, ChoiceKind.OPERATION, "oclIsKindOf"); // doesn't parse choices = helper.getSyntaxHelp( ConstraintKind.POSTCONDITION, "self^^^"); assertNotNull(choices); assertChoice(choices, ChoiceKind.VARIABLE, "color"); choices = helper.getSyntaxHelp( ConstraintKind.POSTCONDITION, "Apple.allInstances()->any(true)^"); assertNotNull(choices); assertChoice(choices, ChoiceKind.OPERATION, "newFruit"); assertChoice(choices, ChoiceKind.OPERATION, "setColor"); assertChoice(choices, ChoiceKind.OPERATION, "label"); assertNotChoice(choices, ChoiceKind.OPERATION, "oclIsKindOf"); choices = helper.getSyntaxHelp( ConstraintKind.POSTCONDITION, "Apple.allInstances()->collect(a : Apple | a^^"); assertNotNull(choices); assertChoice(choices, ChoiceKind.OPERATION, "newFruit"); assertChoice(choices, ChoiceKind.OPERATION, "setColor"); assertChoice(choices, ChoiceKind.OPERATION, "label"); assertNotChoice(choices, ChoiceKind.OPERATION, "oclIsKindOf"); } catch (Exception e) { fail("Parse failed: " + e.getLocalizedMessage()); } } /** * Tests the presentation of signal send choices. */ public void test_contentAssist_signals() { helper.setOperationContext(fruit, fruit_ripen); try { List<Choice> choices = helper.getSyntaxHelp( ConstraintKind.POSTCONDITION, "self^"); assertNotNull(choices); assertChoice(choices, ChoiceKind.SIGNAL, "Drop"); choices = helper.getSyntaxHelp( ConstraintKind.POSTCONDITION, "self^^"); assertNotNull(choices); assertChoice(choices, ChoiceKind.SIGNAL, "Drop"); // doesn't parse choices = helper.getSyntaxHelp( ConstraintKind.POSTCONDITION, "self^^^"); assertNotNull(choices); assertChoice(choices, ChoiceKind.VARIABLE, "color"); choices = helper.getSyntaxHelp( ConstraintKind.POSTCONDITION, "Apple.allInstances()->any(true)^"); assertNotNull(choices); assertChoice(choices, ChoiceKind.SIGNAL, "Drop"); choices = helper.getSyntaxHelp( ConstraintKind.POSTCONDITION, "Apple.allInstances()->collect(a : Apple | a^^"); assertNotNull(choices); assertChoice(choices, ChoiceKind.SIGNAL, "Drop"); } catch (Exception e) { fail("Parse failed: " + e.getLocalizedMessage()); } } }