Commit ce9cd336 authored by Eyrak Paen-Rochlitz's avatar Eyrak Paen-Rochlitz
Browse files

[core.room] fix binding validation to check inherited external end ports

Validation for connection of external end ports now also accounts for
inherited ports. Note that due to current scope provider behavior, it is
not actually possible in the textual editor to encounter this case.
HOWEVER, it does become an issue in the diagram editor, because it
currently uses ValidationUtil on arbitrary ports in the diagram without
consulting the scope.

Issue #46
parent 687d0d35
Pipeline #4294 passed with stage
in 0 seconds
......@@ -29,7 +29,6 @@ import org.eclipse.etrice.core.room.ActorRef;
import org.eclipse.etrice.core.room.Binding;
import org.eclipse.etrice.core.room.BindingEndPoint;
import org.eclipse.etrice.core.room.CommunicationType;
import org.eclipse.etrice.core.room.ExternalPort;
import org.eclipse.etrice.core.room.InterfaceItem;
import org.eclipse.etrice.core.room.LayerConnection;
import org.eclipse.etrice.core.room.Port;
......@@ -68,12 +67,8 @@ public class ValidationUtil extends FSMValidationUtil {
if (!isMultipleConnectable(port, ref) && isConnected(port, ref, acc, exclude))
return Result.error("port with multiplicity 1 is already connected");
if (acc instanceof ActorClass) {
for (ExternalPort xp : ((ActorClass)acc).getExternalPorts()) {
if (xp.getInterfacePort()==port)
return Result.error("external end ports must not be connected");
}
}
if (roomHelpers.getInterfaceItems(acc, true).contains(port) && roomHelpers.isExternal(port))
return Result.error("external end ports must not be connected");
return Result.ok();
}
......
......@@ -83,6 +83,42 @@ RoomModel TestBindings {
}
}
ActorClass Example8_external_to_actorref {
Interface {
conjugated Port external_conj: PC1
}
Structure {
external Port external_conj
ActorRef aref: AC1
// This case is only relevant in diagram, since there the validation
// is used to check endpoints that could otherwise be out of scope
// according to the RoomScopeProvider. Binding is constructed in unit test.
//Binding aref.reg and external_conj
}
}
ActorClass Example9_inherited_external_to_local_actorref extends AC7 {
Structure {
ActorRef aref_sub: AC1
// This case is only relevant in diagram. See Example8 for details.
// Binding is constructed in unit test.
//Binding aref_sub.reg and external_conj
}
}
ActorClass Example10_inherited_external_to_inherited_actorref extends AC7 {
Structure {
// This case is only relevant in diagram. See Example8 for details.
// Binding is constructed in unit test.
//Binding aref.reg and external_conj
}
}
// helper actor classes
ActorClass AC1 {
......@@ -140,6 +176,16 @@ RoomModel TestBindings {
}
}
ActorClass AC7 {
Interface {
conjugated Port external_conj: PC1
}
Structure {
external Port external_conj
ActorRef aref: AC1
}
}
ProtocolClass PC1 {
incoming {
Message in1()
......
......@@ -19,8 +19,13 @@ import static org.junit.Assert.*;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.etrice.core.room.ActorClass;
import org.eclipse.etrice.core.room.ActorContainerRef;
import org.eclipse.etrice.core.room.Binding;
import org.eclipse.etrice.core.room.BindingEndPoint;
import org.eclipse.etrice.core.room.Port;
import org.eclipse.etrice.core.room.RoomFactory;
import org.eclipse.etrice.core.room.RoomModel;
import org.eclipse.etrice.core.room.StructureClass;
import org.junit.Before;
import org.junit.Test;
......@@ -81,6 +86,33 @@ public class TestBindings extends TestBase {
assertEquals("derived protocols not connectable (both directions extended)", diag.getMessage());
}
@Test
public void testLocalExternalToLocalRefValidation() {
ActorClass ac = getActorClass("Example8_external_to_actorref");
Binding bind = createBinding(createEndPoint(ac, "aref", "reg"), createEndPoint(ac, "external_conj"));
ac.getBindings().add(bind);
Diagnostic diag = getDiag(bind).getChildren().get(0);
assertEquals("expect error message", "external end ports must not be connected", diag.getMessage());
}
@Test
public void testInheritedExternalEndPointToLocalRefValidation() {
ActorClass ac = getActorClass("Example9_inherited_external_to_local_actorref");
Binding bind = createBinding(createEndPoint(ac, "aref_sub", "reg"), createEndPoint(ac, "external_conj"));
ac.getBindings().add(bind);
Diagnostic diag = getDiag(bind).getChildren().get(0);
assertEquals("expect error message", "external end ports must not be connected", diag.getMessage());
}
@Test
public void testInheritedExternalToInheritedRefValidation() {
ActorClass ac = getActorClass("Example10_inherited_external_to_inherited_actorref");
Binding bind = createBinding(createEndPoint(ac, "aref", "reg"), createEndPoint(ac, "external_conj"));
ac.getBindings().add(bind);
Diagnostic diag = getDiag(bind).getChildren().get(0);
assertEquals("expect error message", "external end ports must not be connected", diag.getMessage());
}
@Test
public void testProtocolValidation() {
RoomModel mdl = (RoomModel) resource.getContents().get(0);
......@@ -91,7 +123,52 @@ public class TestBindings extends TestBase {
}
private Binding getBinding(String acname, int idx) {
ActorClass ac = (ActorClass) resource.getEObject("ActorClass:"+acname);
ActorClass ac = getActorClass(acname);
return ac.getBindings().get(idx);
}
private ActorClass getActorClass(String acname) {
ActorClass ac = (ActorClass) resource.getEObject("ActorClass:"+acname);
return ac;
}
private Binding createBinding(BindingEndPoint ep1, BindingEndPoint ep2) {
Binding bind = RoomFactory.eINSTANCE.createBinding();
bind.setEndpoint1(ep1);
bind.setEndpoint2(ep2);
return bind;
}
private BindingEndPoint createEndPoint(ActorClass ac, String arefName, String portName) {
BindingEndPoint ep = RoomFactory.eINSTANCE.createBindingEndPoint();
ActorContainerRef aref = getRefByName(arefName, ac);
Port arefPort = getPortByName(portName, aref.getStructureClass());
ep.setActorRef(aref);
ep.setPort(arefPort);
return ep;
}
private BindingEndPoint createEndPoint(ActorClass ac, String portName) {
BindingEndPoint ep = RoomFactory.eINSTANCE.createBindingEndPoint();
Port port = getPortByName(portName, ac);
ep.setPort(port);
return ep;
}
private ActorContainerRef getRefByName(String name, StructureClass sc) {
ActorContainerRef aref = roomHelpers.getAllActorContainerRefs(sc).stream()
.filter(it -> it.getName().equals(name))
.findFirst()
.orElseThrow();
return aref;
}
private Port getPortByName(String name, StructureClass sc) throws ClassCastException {
ActorClass ac = (ActorClass)sc;
Port port = roomHelpers.getAllPorts(ac).stream()
.filter(it -> it.getName().equals(name))
.findFirst()
.orElseThrow();
return port;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment