From 76e84a701ecb4f575648a4cad9bce0049497ad72 Mon Sep 17 00:00:00 2001 From: Lutz Wrage Date: Fri, 18 Sep 2026 12:18:37 -0400 Subject: [PATCH 1/2] Add regression test for issue #2817 Cover noerror constraints on component error, recovery, and repair events and on an event in a reusable behavior machine. Assert the specific diagnostic on each condition and reject unrelated diagnostics. Preserve valid event type constraints and noerror conditions on incoming and subcomponent outgoing propagations. Before the fix, the valid model passes and both negative tests fail because typed events lack the required diagnostic. --- .../models/issue2817/.gitignore | 2 + .../models/issue2817/.project | 18 ++++ .../models/issue2817/Issue2817.aadl | 29 ++++++ .../models/issue2817/MachineEvents.aadl | 15 +++ .../models/issue2817/ValidConditions.aadl | 60 +++++++++++ .../tests/issues/Issue2817Test.java | 99 +++++++++++++++++++ 6 files changed, 223 insertions(+) create mode 100644 emv2/org.osate.aadl2.errormodel.tests/models/issue2817/.gitignore create mode 100644 emv2/org.osate.aadl2.errormodel.tests/models/issue2817/.project create mode 100644 emv2/org.osate.aadl2.errormodel.tests/models/issue2817/Issue2817.aadl create mode 100644 emv2/org.osate.aadl2.errormodel.tests/models/issue2817/MachineEvents.aadl create mode 100644 emv2/org.osate.aadl2.errormodel.tests/models/issue2817/ValidConditions.aadl create mode 100644 emv2/org.osate.aadl2.errormodel.tests/src/org/osate/aadl2/errormodel/tests/issues/Issue2817Test.java diff --git a/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/.gitignore b/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/.gitignore new file mode 100644 index 00000000000..afce51184c6 --- /dev/null +++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/.gitignore @@ -0,0 +1,2 @@ +/.aadlbin-gen/ +/instances/ diff --git a/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/.project b/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/.project new file mode 100644 index 00000000000..0195361dd29 --- /dev/null +++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/.project @@ -0,0 +1,18 @@ + + + issue2817 + + + + + + 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/issue2817/Issue2817.aadl b/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/Issue2817.aadl new file mode 100644 index 00000000000..c7ba595ba69 --- /dev/null +++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/Issue2817.aadl @@ -0,0 +1,29 @@ +package Issue2817 +public + annex EMV2 {** + error behavior Machine + states + state1: initial state; + state2: state; + end behavior; + **}; + + system S + annex EMV2 {** + use types ErrorLibrary; + use behavior Issue2817::Machine; + component error behavior + events + typed: error event {CommonErrors}; + untyped: error event; + recovery: recover event; + repair1: repair event; + transitions + typed_event: state1 -[typed {ServiceError} and typed {noerror}]-> state2; + untyped_event: state1 -[untyped {noerror}]-> state2; + recover_event: state1 -[recovery {noerror}]-> state2; + repair_event: state1 -[repair1 {noerror}]-> state2; + end component; + **}; + end S; +end Issue2817; diff --git a/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/MachineEvents.aadl b/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/MachineEvents.aadl new file mode 100644 index 00000000000..a00d9180c37 --- /dev/null +++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/MachineEvents.aadl @@ -0,0 +1,15 @@ +package MachineEvents +public + annex EMV2 {** + error behavior Machine + use types ErrorLibrary; + events + typed: error event {CommonErrors}; + states + state1: initial state; + state2: state; + transitions + state1 -[typed {noerror}]-> state2; + end behavior; + **}; +end MachineEvents; diff --git a/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/ValidConditions.aadl b/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/ValidConditions.aadl new file mode 100644 index 00000000000..06fd794132d --- /dev/null +++ b/emv2/org.osate.aadl2.errormodel.tests/models/issue2817/ValidConditions.aadl @@ -0,0 +1,60 @@ +package ValidConditions +public + annex EMV2 {** + error behavior Machine + states + state1: initial state; + state2: state; + end behavior; + **}; + + system S + features + f1: in feature; + f2: in feature; + annex EMV2 {** + use types ErrorLibrary; + use behavior ValidConditions::Machine; + error propagations + f1: in propagation {CommonErrors}; + f2: in propagation {CommonErrors}; + end propagations; + component error behavior + events + typed: error event {CommonErrors}; + untyped: error event; + recovery: recover event; + repair1: repair event; + transitions + incoming: state1 -[f1 {ServiceError} and f2 {noerror}]-> state2; + typed_event: state1 -[typed {ServiceError}]-> state2; + unconstrained_event: state1 -[typed]-> state2; + untyped_event: state1 -[untyped]-> state2; + recover_event: state1 -[recovery]-> state2; + repair_event: state1 -[repair1]-> state2; + end component; + **}; + end S; + + system implementation S.i + subcomponents + child: system Child; + annex EMV2 {** + component error behavior + transitions + outgoing: state1 -[child.f {noerror}]-> state2; + end component; + **}; + end S.i; + + system Child + features + f: out feature; + annex EMV2 {** + use types ErrorLibrary; + error propagations + f: out propagation {CommonErrors}; + end propagations; + **}; + end Child; +end ValidConditions; diff --git a/emv2/org.osate.aadl2.errormodel.tests/src/org/osate/aadl2/errormodel/tests/issues/Issue2817Test.java b/emv2/org.osate.aadl2.errormodel.tests/src/org/osate/aadl2/errormodel/tests/issues/Issue2817Test.java new file mode 100644 index 00000000000..2ac595772a0 --- /dev/null +++ b/emv2/org.osate.aadl2.errormodel.tests/src/org/osate/aadl2/errormodel/tests/issues/Issue2817Test.java @@ -0,0 +1,99 @@ +/** + * 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 static org.junit.Assert.assertEquals; + +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.DefaultAnnexLibrary; +import org.osate.aadl2.DefaultAnnexSubclause; +import org.osate.aadl2.SystemType; +import org.osate.aadl2.errormodel.tests.ErrorModelInjectorProvider; +import org.osate.testsupport.AssertHelper; +import org.osate.testsupport.TestHelper; +import org.osate.xtext.aadl2.errormodel.errorModel.AndExpression; +import org.osate.xtext.aadl2.errormodel.errorModel.ErrorModelLibrary; +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 Issue2817Test extends XtextTest { + private static final String PATH = "org.osate.aadl2.errormodel.tests/models/issue2817/"; + private static final String MESSAGE = "The noerror constraint is not permitted on an event."; + + @Inject + private TestHelper testHelper; + + @Inject + private ValidationTestHelper validationHelper; + + @Test + public void rejectsNoerrorOnComponentEvents() throws Exception { + var result = issues = testHelper.testFile(PATH + "Issue2817.aadl"); + var expected = new FluentIssueCollection(result.getResource(), new ArrayList<>(), new ArrayList<>()); + var pkg = (AadlPackage) result.getResource().getContents().getFirst(); + var system = (SystemType) pkg.getPublicSection().getOwnedClassifiers().getFirst(); + var annex = (ErrorModelSubclause) ((DefaultAnnexSubclause) system.getOwnedAnnexSubclauses().getFirst()) + .getParsedAnnexSubclause(); + var conjunction = (AndExpression) annex.getTransitions().get(0).getCondition(); + AssertHelper.assertError(conjunction.getOperands().get(1), result.getIssues(), expected, MESSAGE); + for (int i = 1; i < 4; i++) { + AssertHelper.assertError(annex.getTransitions().get(i).getCondition(), result.getIssues(), expected, MESSAGE); + } + assertEquals(4, result.getIssues().size()); + expected.sizeIs(4); + assertConstraints(expected); + } + + @Test + public void rejectsNoerrorOnBehaviorMachineEvents() throws Exception { + var result = issues = testHelper.testFile(PATH + "MachineEvents.aadl"); + var expected = new FluentIssueCollection(result.getResource(), new ArrayList<>(), new ArrayList<>()); + var pkg = (AadlPackage) result.getResource().getContents().getFirst(); + var library = (ErrorModelLibrary) ((DefaultAnnexLibrary) pkg.getPublicSection().getOwnedAnnexLibraries() + .getFirst()).getParsedAnnexLibrary(); + var condition = library.getBehaviors().getFirst().getTransitions().getFirst().getCondition(); + AssertHelper.assertError(condition, result.getIssues(), expected, MESSAGE); + assertEquals(1, result.getIssues().size()); + expected.sizeIs(1); + assertConstraints(expected); + } + + @Test + public void acceptsEventTypeConstraintsAndNoerrorOnPropagations() throws Exception { + var pkg = testHelper.parseFile(PATH + "ValidConditions.aadl"); + validationHelper.assertNoIssues(pkg); + } +} From e8d01a42da2d23a73a4aaaa18120f0dd9b3b9c4e Mon Sep 17 00:00:00 2001 From: Lutz Wrage Date: Fri, 18 Sep 2026 12:20:19 -0400 Subject: [PATCH 2/2] Reject noerror constraints on EMV2 events Check for noerror on every ErrorBehaviorEvent before the existing type-set checks. This reports a specific error for typed and untyped error events, recovery events, and repair events while preserving noerror on propagations. Keep the grammar and metamodel unchanged, as requested by issue #2817. The three focused regression tests pass. --- .../aadl2/errormodel/validation/ErrorModelValidator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 821454b3d5c..df3c42fd967 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 @@ -547,7 +547,9 @@ private void checkConditionElementType(ConditionElement conditionElement) { if (condTS == null) { return; } - if (triggerTS == null && condTS != null) { + if (ep instanceof ErrorBehaviorEvent && EMV2TypeSetUtil.isNoError(condTS)) { + error(conditionElement, "The noerror constraint is not permitted on an event."); + } else if (triggerTS == null && condTS != null) { // it is ok for a state not to have a type set. error(conditionElement, "Condition has type constraint but referenced " + triggerName + " does not."); } else if (!EMV2TypeSetUtil.isNoError(condTS) && !EMV2TypeSetUtil.contains(triggerTS, condTS)) {