diff --git a/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/.gitignore b/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/.gitignore new file mode 100644 index 0000000000..afce51184c --- /dev/null +++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/.gitignore @@ -0,0 +1,2 @@ +/.aadlbin-gen/ +/instances/ diff --git a/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/.project b/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/.project new file mode 100644 index 0000000000..41d3e11aca --- /dev/null +++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/.project @@ -0,0 +1,18 @@ + + + issue2820 + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + + org.osate.core.aadlnature + org.eclipse.xtext.ui.shared.xtextNature + + diff --git a/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/InvalidSums.aadl b/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/InvalidSums.aadl new file mode 100644 index 0000000000..ebd521145e --- /dev/null +++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/InvalidSums.aadl @@ -0,0 +1,51 @@ +package InvalidSums +public + with ProbabilityProperties, Issue2820; + + system precise_excess + annex EMV2 {** + use behavior Issue2820::machine; + component error behavior + transitions + t: state1 -[event1]-> (state2 with 0.2, state3 with ProbabilityProperties::probability); + end component; + properties + ProbabilityProperties::probability => 0.800000000000000001 applies to t; + **}; + end precise_excess; + + system ordinary_shortfall + annex EMV2 {** + use behavior Issue2820::machine; + component error behavior + transitions + t: state1 -[event1]-> (state2 with 0.2, state3 with ProbabilityProperties::probability); + end component; + properties + ProbabilityProperties::probability => 0.7 applies to t; + **}; + end ordinary_shortfall; + + system exhausted_remainder + annex EMV2 {** + use behavior Issue2820::machine; + component error behavior + transitions + t: state1 -[event1]-> (state2 with 0.2, state3 with ProbabilityProperties::probability, same state with others); + end component; + properties + ProbabilityProperties::probability => 0.8 applies to t; + **}; + end exhausted_remainder; + + system literal_shortfall + annex EMV2 {** + use behavior Issue2820::machine; + component error behavior + transitions + t: state1 -[event1]-> (state2 with 0.2, state3 with 0.7); + end component; + **}; + end literal_shortfall; + +end InvalidSums; diff --git a/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/Issue2820.aadl b/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/Issue2820.aadl new file mode 100644 index 0000000000..1a074be9c7 --- /dev/null +++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/Issue2820.aadl @@ -0,0 +1,75 @@ +package Issue2820 +public + with ProbabilityProperties; + + system decimal_value + annex EMV2 {** + use behavior Issue2820::machine; + component error behavior + transitions + t: state1 -[event1]-> (state2 with 0.2, state3 with ProbabilityProperties::probability); + end component; + properties + ProbabilityProperties::probability => 0.8 applies to t; + **}; + end decimal_value; + + system precise_value + annex EMV2 {** + use behavior Issue2820::machine; + component error behavior + transitions + t: state1 -[event1]-> (state2 with 0.200000000000000001, state3 with ProbabilityProperties::probability); + end component; + properties + ProbabilityProperties::probability => 0.799999999999999999 applies to t; + **}; + end precise_value; + + system constant_value + annex EMV2 {** + use behavior Issue2820::machine; + component error behavior + transitions + t: state1 -[event1]-> (state2 with 0.2, state3 with ProbabilityProperties::probability); + end component; + properties + ProbabilityProperties::probability => ProbabilityProperties::complement applies to t; + **}; + end constant_value; + + system formatted_value + annex EMV2 {** + use behavior Issue2820::machine; + component error behavior + transitions + t: state1 -[event1]-> (state2 with 0.2, state3 with ProbabilityProperties::probability); + end component; + properties + ProbabilityProperties::probability => +8.0_0e-1 applies to t; + **}; + end formatted_value; + + system precise_remainder + annex EMV2 {** + use behavior Issue2820::machine; + component error behavior + transitions + t: state1 -[event1]-> (state2 with 0.2, state3 with ProbabilityProperties::probability, same state with others); + end component; + properties + ProbabilityProperties::probability => 0.799999999999999999 applies to t; + **}; + end precise_remainder; + + annex EMV2 {** + error behavior machine + events + event1: error event; + states + state1: initial state; + state2: state; + state3: state; + end behavior; + **}; +end Issue2820; diff --git a/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/ProbabilityProperties.aadl b/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/ProbabilityProperties.aadl new file mode 100644 index 0000000000..56d45b9c2b --- /dev/null +++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2820/ProbabilityProperties.aadl @@ -0,0 +1,4 @@ +property set ProbabilityProperties is + probability: aadlreal applies to (all); + complement: constant aadlreal => +8.0e-1; +end ProbabilityProperties; diff --git a/emv2/org.osate.aadl2.errormodel.tests/src/org/osate/aadl2/errormodel/tests/issues/Issue2820Test.java b/emv2/org.osate.aadl2.errormodel.tests/src/org/osate/aadl2/errormodel/tests/issues/Issue2820Test.java new file mode 100644 index 0000000000..30b3315bcd --- /dev/null +++ b/emv2/org.osate.aadl2.errormodel.tests/src/org/osate/aadl2/errormodel/tests/issues/Issue2820Test.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2004-2026 Carnegie Mellon University and others. (see Contributors file). + * All Rights Reserved. + * + * NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE + * OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT + * MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT. + * + * This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * SPDX-License-Identifier: EPL-2.0 + * + * Created, in part, with funding and support from the United States Government. (see Acknowledgments file). + * + * This program includes and/or can make use of certain third party source code, object code, documentation and other + * files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system + * configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and + * conditions contained in any such Third Party Software or separate license file distributed with such Third Party + * Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici- + * aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li- + * censes only apply to the Third Party Software and not any other portion of this program or this program as a whole. + */ +package org.osate.aadl2.errormodel.tests.issues; + +import java.util.ArrayList; + +import org.eclipse.xtext.testing.InjectWith; +import org.eclipse.xtext.testing.XtextRunner; +import org.eclipse.xtext.testing.validation.ValidationTestHelper; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.osate.aadl2.AadlPackage; +import org.osate.aadl2.DefaultAnnexSubclause; +import org.osate.aadl2.errormodel.tests.ErrorModelInjectorProvider; +import org.osate.testsupport.AssertHelper; +import org.osate.testsupport.TestHelper; +import org.osate.xtext.aadl2.errormodel.errorModel.ErrorModelSubclause; + +import com.google.inject.Inject; +import com.itemis.xtext.testing.FluentIssueCollection; +import com.itemis.xtext.testing.XtextTest; + +@RunWith(XtextRunner.class) +@InjectWith(ErrorModelInjectorProvider.class) +public class Issue2820Test extends XtextTest { + private static final String PROJECT_LOCATION = "org.osate.aadl2.errormodel.tests/models/issue2820/"; + private static final String PROPERTIES = PROJECT_LOCATION + "ProbabilityProperties.aadl"; + + @Inject + private TestHelper testHelper; + + @Inject + private ValidationTestHelper validationHelper; + + @Test + public void preserveExactDecimalPropertyProbabilities() { + validationHelper.assertNoIssues(testHelper.parseFile(PROJECT_LOCATION + "Issue2820.aadl", PROPERTIES)); + } + + @Test + public void rejectIncorrectSumsWithoutRoundingThemToOne() throws Exception { + var result = issues = testHelper.testFile(PROJECT_LOCATION + "InvalidSums.aadl", PROPERTIES, + PROJECT_LOCATION + "Issue2820.aadl"); + var expected = new FluentIssueCollection(result.getResource(), new ArrayList<>(), new ArrayList<>()); + var pkg = (AadlPackage) result.getResource().getContents().getFirst(); + for (var classifier : pkg.getPublicSection().getOwnedClassifiers()) { + var annex = (ErrorModelSubclause) ((DefaultAnnexSubclause) classifier.getOwnedAnnexSubclauses().getFirst()) + .getParsedAnnexSubclause(); + var message = classifier.getName().equals("exhausted_remainder") + ? "Sum of branch probabilities must be less than 1 due to 'others'" + : "Sum of branch probabilities must be 1"; + AssertHelper.assertError(annex.getTransitions().getFirst(), result.getIssues(), expected, message); + } + expected.sizeIs(4); + assertConstraints(expected); + } +} diff --git a/emv2/org.osate.xtext.aadl2.errormodel/src/org/osate/xtext/aadl2/errormodel/validation/ErrorModelValidator.java b/emv2/org.osate.xtext.aadl2.errormodel/src/org/osate/xtext/aadl2/errormodel/validation/ErrorModelValidator.java index 9230b778d3..ef4f304c3f 100644 --- a/emv2/org.osate.xtext.aadl2.errormodel/src/org/osate/xtext/aadl2/errormodel/validation/ErrorModelValidator.java +++ b/emv2/org.osate.xtext.aadl2.errormodel/src/org/osate/xtext/aadl2/errormodel/validation/ErrorModelValidator.java @@ -36,6 +36,7 @@ import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.xtext.EcoreUtil2; +import org.eclipse.xtext.nodemodel.util.NodeModelUtils; import org.eclipse.xtext.validation.Check; import org.eclipse.xtext.validation.CheckType; import org.osate.aadl2.Aadl2Package; @@ -60,6 +61,7 @@ import org.osate.aadl2.Property; import org.osate.aadl2.PropertyAssociation; import org.osate.aadl2.PropertyType; +import org.osate.aadl2.RealLiteral; import org.osate.aadl2.Subcomponent; import org.osate.aadl2.modelsupport.util.AadlUtil; import org.osate.aadl2.util.Aadl2Util; @@ -1104,8 +1106,7 @@ private void checkBranches(ErrorBehaviorTransition ebt) { Classifier cl = EMV2Util.getAssociatedClassifier(ebt); List pa = EMV2Properties.getProperty(sl.getQualifiedName(), cl, ebt, null); for (EMV2PropertyAssociation emv2PropertyAssociation : pa) { - prob = prob.add(new BigDecimal(EMV2Properties.getRealValue(emv2PropertyAssociation), - MathContext.UNLIMITED)); + prob = prob.add(getBranchPropertyValue(emv2PropertyAssociation)); } } } @@ -1117,6 +1118,18 @@ private void checkBranches(ErrorBehaviorTransition ebt) { } } + private BigDecimal getBranchPropertyValue(EMV2PropertyAssociation association) { + if (EMV2Properties.getPropertyValue(association) instanceof RealLiteral literal) { + var nodes = NodeModelUtils.findNodesForFeature(literal, Aadl2Package.eINSTANCE.getRealLiteral_Value()); + if (!nodes.isEmpty()) { + var text = NodeModelUtils.getTokenText(nodes.getFirst()).replaceAll("[\\s_]", ""); + return new BigDecimal(text); + } + return BigDecimal.valueOf(literal.getValue()); + } + return BigDecimal.ZERO; + } + private void checkTransitionTargetTypes(TransitionBranch ebt) { if (ebt.isSteadyState()) { return;