Skip to content
Snippets Groups Projects
Commit 2a281c3e authored by René Schöne's avatar René Schöne
Browse files

working on attributes as endpoint target

- change syntax in connect file, avoid colon
- begin with AttributeTest
- discovered error when endpoint is connected twice
parent 2e0b5b38
No related branches found
No related tags found
1 merge request!25Resolve "Feature: Send endpoint for attributes"
Showing
with 215 additions and 22 deletions
...@@ -2,6 +2,19 @@ aspect Analysis { ...@@ -2,6 +2,19 @@ aspect Analysis {
// --- isAlreadyDefined --- // --- isAlreadyDefined ---
syn boolean EndpointDefinition.isAlreadyDefined() = getEndpointTarget().isAlreadyDefined(); syn boolean EndpointDefinition.isAlreadyDefined() = getEndpointTarget().isAlreadyDefined();
syn boolean EndpointTarget.isAlreadyDefined(); syn boolean EndpointTarget.isAlreadyDefined();
eq AttributeEndpointTarget.isAlreadyDefined() {
// define lookup here, as not used elsewhere
int numberOfSameDefs = 0;
for (EndpointTarget target : ragconnect().givenEndpointTargetList()) {
if (target.isAttributeEndpointTarget()) {
AttributeEndpointTarget other = target.asAttributeEndpointTarget();
if (other.getParentTypeDecl().equals(this.getParentTypeDecl()) && other.getName().equals(this.getName())) {
numberOfSameDefs += 1;
}
}
}
return numberOfSameDefs > 1;
}
eq TokenEndpointTarget.isAlreadyDefined() { eq TokenEndpointTarget.isAlreadyDefined() {
return lookupTokenEndpointDefinitions(getToken()).stream() return lookupTokenEndpointDefinitions(getToken()).stream()
.filter(containingEndpointDefinition()::matchesType) .filter(containingEndpointDefinition()::matchesType)
...@@ -63,8 +76,9 @@ aspect Analysis { ...@@ -63,8 +76,9 @@ aspect Analysis {
} }
} }
// TODO rename entityIsNormalAttribute to actual meaning
syn boolean EndpointTarget.entityIsNormalAttribute(); syn boolean EndpointTarget.entityIsNormalAttribute();
// TODO AttributeEndpointTarget.entityIsNormalAttribute eq AttributeEndpointTarget.entityIsNormalAttribute() = true;
eq TokenEndpointTarget.entityIsNormalAttribute() = !getToken().getNTA(); eq TokenEndpointTarget.entityIsNormalAttribute() = !getToken().getNTA();
eq TypeEndpointTarget.entityIsNormalAttribute() = !getType().getNTA(); eq TypeEndpointTarget.entityIsNormalAttribute() = !getType().getNTA();
eq ContextFreeTypeEndpointTarget.entityIsNormalAttribute() = false; eq ContextFreeTypeEndpointTarget.entityIsNormalAttribute() = false;
......
...@@ -168,6 +168,11 @@ aspect MustacheMappingApplicationAndDefinition { ...@@ -168,6 +168,11 @@ aspect MustacheMappingApplicationAndDefinition {
syn String MEndpointDefinition.preemptiveReturn(); syn String MEndpointDefinition.preemptiveReturn();
syn String MEndpointDefinition.firstInputVarName(); syn String MEndpointDefinition.firstInputVarName();
// TODO check MAttributeSendDefinition
eq MAttributeSendDefinition.firstInputVarName() = getterMethodCall();
eq MAttributeSendDefinition.preemptiveExpectedValue() = lastValueGetterCall();
eq MAttributeSendDefinition.preemptiveReturn() = "return false;";
eq MTokenReceiveDefinition.firstInputVarName() = "message"; eq MTokenReceiveDefinition.firstInputVarName() = "message";
eq MTokenReceiveDefinition.preemptiveExpectedValue() = getterMethodCall(); eq MTokenReceiveDefinition.preemptiveExpectedValue() = getterMethodCall();
eq MTokenReceiveDefinition.preemptiveReturn() = "return;"; eq MTokenReceiveDefinition.preemptiveReturn() = "return;";
...@@ -323,7 +328,7 @@ aspect MustacheRagConnect { ...@@ -323,7 +328,7 @@ aspect MustacheRagConnect {
aspect MustacheReceiveAndSendAndHandleUri { aspect MustacheReceiveAndSendAndHandleUri {
// === EndpointDefinition === // === EndpointDefinition ===
syn String EndpointDefinition.connectMethodName() = "connect" + entityName(); syn String EndpointDefinition.connectMethodName() = "connect" + capitalize(entityName());
syn String EndpointDefinition.connectParameterName() = "uriString"; syn String EndpointDefinition.connectParameterName() = "uriString";
...@@ -348,7 +353,7 @@ aspect MustacheReceiveAndSendAndHandleUri { ...@@ -348,7 +353,7 @@ aspect MustacheReceiveAndSendAndHandleUri {
} else { } else {
extra = ""; extra = "";
} }
return "disconnect" + extra + entityName(); return "disconnect" + extra + capitalize(entityName());
} }
syn String EndpointDefinition.entityName() = getEndpointTarget().entityName(); syn String EndpointDefinition.entityName() = getEndpointTarget().entityName();
...@@ -371,7 +376,7 @@ aspect MustacheReceiveAndSendAndHandleUri { ...@@ -371,7 +376,7 @@ aspect MustacheReceiveAndSendAndHandleUri {
syn String EndpointTarget.parentTypeName(); syn String EndpointTarget.parentTypeName();
syn String EndpointTarget.entityName(); syn String EndpointTarget.entityName();
// TODO AttributeEndpointTarget.getterName eq AttributeEndpointTarget.getterMethodName() = getName();
eq AttributeEndpointTarget.parentTypeName() = getParentTypeDecl().getName(); eq AttributeEndpointTarget.parentTypeName() = getParentTypeDecl().getName();
eq AttributeEndpointTarget.entityName() = getName(); eq AttributeEndpointTarget.entityName() = getName();
...@@ -463,9 +468,14 @@ aspect MustacheSendDefinition { ...@@ -463,9 +468,14 @@ aspect MustacheSendDefinition {
syn String EndpointTarget.senderName() = ragconnect().internalRagConnectPrefix() + "_sender_" + entityName(); syn String EndpointTarget.senderName() = ragconnect().internalRagConnectPrefix() + "_sender_" + entityName();
eq ContextFreeTypeEndpointTarget.senderName() = null; eq ContextFreeTypeEndpointTarget.senderName() = null;
// TOOO both updateMethodName and writeMethodName could be defined for MEndpointDefinition using getEndpointDefinition().enitityName()
syn String MEndpointDefinition.updateMethodName(); syn String MEndpointDefinition.updateMethodName();
syn String MEndpointDefinition.writeMethodName(); syn String MEndpointDefinition.writeMethodName();
// TODO check MAttributeSendDefinition. maybe name-clash possible if there is an attribute with same name as a child
eq MAttributeSendDefinition.updateMethodName() = ragconnect().internalRagConnectPrefix() + "_update_" + getEndpointDefinition().entityName();
eq MAttributeSendDefinition.writeMethodName() = ragconnect().internalRagConnectPrefix() + "_writeLastValue_" + getEndpointDefinition().entityName();
eq MTokenReceiveDefinition.updateMethodName() = null; eq MTokenReceiveDefinition.updateMethodName() = null;
eq MTokenReceiveDefinition.writeMethodName() = null; eq MTokenReceiveDefinition.writeMethodName() = null;
...@@ -582,6 +592,12 @@ aspect AttributesForMustache { ...@@ -582,6 +592,12 @@ aspect AttributesForMustache {
return result; return result;
} }
abstract MEndpointDefinition EndpointTarget.createMEndpointDefinition(boolean isSend); abstract MEndpointDefinition EndpointTarget.createMEndpointDefinition(boolean isSend);
MEndpointDefinition AttributeEndpointTarget.createMEndpointDefinition(boolean isSend) {
if (!isSend) {
throw new IllegalArgumentException("AttributeEndpointTarget can only be sent!");
}
return new MAttributeSendDefinition();
}
MEndpointDefinition TokenEndpointTarget.createMEndpointDefinition(boolean isSend) { MEndpointDefinition TokenEndpointTarget.createMEndpointDefinition(boolean isSend) {
return isSend ? new MTokenSendDefinition() : new MTokenReceiveDefinition(); return isSend ? new MTokenSendDefinition() : new MTokenReceiveDefinition();
} }
......
abstract MEndpointDefinition ::= InnerMappingDefinition:MInnerMappingDefinition*; abstract MEndpointDefinition ::= InnerMappingDefinition:MInnerMappingDefinition*;
rel MEndpointDefinition.EndpointDefinition -> EndpointDefinition; rel MEndpointDefinition.EndpointDefinition -> EndpointDefinition;
MAttributeSendDefinition : MEndpointDefinition;
abstract MTokenEndpointDefinition : MEndpointDefinition; abstract MTokenEndpointDefinition : MEndpointDefinition;
MTokenReceiveDefinition : MTokenEndpointDefinition; MTokenReceiveDefinition : MTokenEndpointDefinition;
MTokenSendDefinition : MTokenEndpointDefinition; MTokenSendDefinition : MTokenEndpointDefinition;
......
...@@ -25,6 +25,12 @@ aspect NewStuff { ...@@ -25,6 +25,12 @@ aspect NewStuff {
syn boolean EndpointTarget.isUntypedEndpointTarget() = false; syn boolean EndpointTarget.isUntypedEndpointTarget() = false;
eq UntypedEndpointTarget.isUntypedEndpointTarget() = true; eq UntypedEndpointTarget.isUntypedEndpointTarget() = true;
/** Tests if EndpointTarget is a AttributeEndpointTarget.
* @return 'true' if this is a AttributeEndpointTarget, otherwise 'false'
*/
syn boolean EndpointTarget.isAttributeEndpointTarget() = false;
eq AttributeEndpointTarget.isAttributeEndpointTarget() = true;
/** casts a EndpointTarget into a TokenEndpointTarget if possible. /** casts a EndpointTarget into a TokenEndpointTarget if possible.
* @return 'this' cast to a TokenEndpointTarget or 'null' * @return 'this' cast to a TokenEndpointTarget or 'null'
*/ */
...@@ -52,6 +58,13 @@ aspect NewStuff { ...@@ -52,6 +58,13 @@ aspect NewStuff {
syn UntypedEndpointTarget EndpointTarget.asUntypedEndpointTarget(); syn UntypedEndpointTarget EndpointTarget.asUntypedEndpointTarget();
eq EndpointTarget.asUntypedEndpointTarget() = null; eq EndpointTarget.asUntypedEndpointTarget() = null;
eq UntypedEndpointTarget.asUntypedEndpointTarget() = this; eq UntypedEndpointTarget.asUntypedEndpointTarget() = this;
/** casts a EndpointTarget into a AttributeEndpointTarget if possible.
* @return 'this' cast to a AttributeEndpointTarget or 'null'
*/
syn AttributeEndpointTarget EndpointTarget.asAttributeEndpointTarget();
eq EndpointTarget.asAttributeEndpointTarget() = null;
eq AttributeEndpointTarget.asAttributeEndpointTarget() = this;
} }
aspect RagConnectNavigation { aspect RagConnectNavigation {
......
...@@ -63,7 +63,7 @@ EndpointDefinition endpoint_definition_type ...@@ -63,7 +63,7 @@ EndpointDefinition endpoint_definition_type
EndpointTarget endpoint_target EndpointTarget endpoint_target
= ID.type_name DOT ID.child_name {: return new UntypedEndpointTarget(type_name, child_name, false); :} = ID.type_name DOT ID.child_name {: return new UntypedEndpointTarget(type_name, child_name, false); :}
| ID.type_name DOT ID.child_name BRACKETS COLON ID.attribute_type_name | ID.type_name DOT ID.child_name BRACKET_LEFT ID.attribute_type_name BRACKET_RIGHT
{: return new UntypedEndpointTarget(type_name, child_name + ":" + attribute_type_name, true); :} {: return new UntypedEndpointTarget(type_name, child_name + ":" + attribute_type_name, true); :}
| ID.type_name {: return new UntypedEndpointTarget(type_name, "", false); :} | ID.type_name {: return new UntypedEndpointTarget(type_name, "", false); :}
; ;
......
...@@ -8,5 +8,5 @@ ...@@ -8,5 +8,5 @@
"with" { return sym(Terminals.WITH); } "with" { return sym(Terminals.WITH); }
"indexed" { return sym(Terminals.INDEXED); } "indexed" { return sym(Terminals.INDEXED); }
"add" { return sym(Terminals.ADD); } "add" { return sym(Terminals.ADD); }
"()" { return sym(Terminals.BRACKETS); } "(" { return sym(Terminals.BRACKET_LEFT); }
":" { return sym(Terminals.COLON); } ")" { return sym(Terminals.BRACKET_RIGHT); }
...@@ -110,6 +110,10 @@ aspect RagConnectHandler { ...@@ -110,6 +110,10 @@ aspect RagConnectHandler {
senders.forEach(Runnable::run); senders.forEach(Runnable::run);
} }
void run(RagConnectToken token) {
tokenToSender.get(token).run();
}
byte[] getLastValue() { byte[] getLastValue() {
return lastValue; return lastValue;
} }
...@@ -150,6 +154,10 @@ aspect RagConnectHandler { ...@@ -150,6 +154,10 @@ aspect RagConnectHandler {
java.util.Optional.ofNullable(publishers.get(index)).ifPresent(RagConnectPublisher::run); java.util.Optional.ofNullable(publishers.get(index)).ifPresent(RagConnectPublisher::run);
} }
void run(int index, RagConnectToken token) {
java.util.Optional.ofNullable(publishers.get(index)).ifPresent(publisher -> publisher.run(token));
}
byte[] getLastValue(int index) { byte[] getLastValue(int index) {
RagConnectPublisher publisher = publishers.get(index); RagConnectPublisher publisher = publishers.get(index);
if (publisher == null) { if (publisher == null) {
......
...@@ -18,7 +18,7 @@ public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParamete ...@@ -18,7 +18,7 @@ public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParamete
}{{#IndexBasedListAccess}}, index{{/IndexBasedListAccess}}, connectToken); }{{#IndexBasedListAccess}}, index{{/IndexBasedListAccess}}, connectToken);
{{updateMethodName}}({{#IndexBasedListAccess}}index{{/IndexBasedListAccess}}); {{updateMethodName}}({{#IndexBasedListAccess}}index{{/IndexBasedListAccess}});
if (writeCurrentValue) { if (writeCurrentValue) {
{{writeMethodName}}({{#IndexBasedListAccess}}index{{/IndexBasedListAccess}}); {{writeMethodName}}({{#IndexBasedListAccess}}index, {{/IndexBasedListAccess}}connectToken);
} }
success = true; success = true;
break; break;
...@@ -49,7 +49,7 @@ public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParamete ...@@ -49,7 +49,7 @@ public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParamete
{{#IndexBasedListAccess}}index,{{/IndexBasedListAccess}} {{#IndexBasedListAccess}}index,{{/IndexBasedListAccess}}
() -> { () -> {
if (this.{{updateMethodName}}({{#IndexBasedListAccess}}index{{/IndexBasedListAccess}})) { if (this.{{updateMethodName}}({{#IndexBasedListAccess}}index{{/IndexBasedListAccess}})) {
this.{{writeMethodName}}({{#IndexBasedListAccess}}index{{/IndexBasedListAccess}}); this.{{writeMethodName}}({{#IndexBasedListAccess}}index, {{/IndexBasedListAccess}}connectToken);
} }
} }
); );
...@@ -106,8 +106,8 @@ protected boolean {{parentTypeName}}.{{updateMethodName}}({{#IndexBasedListAcces ...@@ -106,8 +106,8 @@ protected boolean {{parentTypeName}}.{{updateMethodName}}({{#IndexBasedListAcces
return {{senderName}} != null; return {{senderName}} != null;
} }
protected void {{parentTypeName}}.{{writeMethodName}}({{#IndexBasedListAccess}}int index{{/IndexBasedListAccess}}) { protected void {{parentTypeName}}.{{writeMethodName}}({{#IndexBasedListAccess}}int index, {{/IndexBasedListAccess}}RagConnectToken token) {
{{senderName}}.run({{#IndexBasedListAccess}}index{{/IndexBasedListAccess}}); {{senderName}}.run({{#IndexBasedListAccess}}index, {{/IndexBasedListAccess}}token);
} }
{{#needForwardingNTA}} {{#needForwardingNTA}}
......
...@@ -50,6 +50,7 @@ dependencies { ...@@ -50,6 +50,7 @@ dependencies {
testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.4.0' testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.4.0'
testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.12.1' testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.12.1'
testImplementation group: 'org.awaitility', name: 'awaitility', version: '4.1.1' testImplementation group: 'org.awaitility', name: 'awaitility', version: '4.1.1'
testImplementation group: 'de.tudresden.inf.st', name: 'dumpAst', version: '0.3.5'
// jackson (for serialization of types) // jackson (for serialization of types)
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.12.1' implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.12.1'
......
send SenderRoot.basic():String ; send SenderRoot.basic(String) ;
send SenderRoot.simple():String ; send SenderRoot.simple(String) ;
send SenderRoot.transformed():int ; send SenderRoot.transformed(int) ;
send SenderRoot.toReferenceType():A ; send SenderRoot.toReferenceType(A) ;
send SenderRoot.toNTA():A ; send SenderRoot.toNTA(A) ;
AddSuffix maps A a to A {: AddSuffix maps A a to A {:
A result = new A(); A result = new A();
String changedValue = a.getValue() + "post"; String changedValue = a.getValue() + "post";
result.setValue(changedValue); result.setValue(changedValue);
result.setInner(new Inner("inner" + changedValue)); result.setInner(new Inner("inner" + a.getInner().getInnerValue()));
return result; return result;
:} :}
......
Root ::= SenderRoot ReceiverRoot; Root ::= SenderRoot* ReceiverRoot;
SenderRoot ::= <Input> ; SenderRoot ::= <Input> ;
ReceiverRoot ::= ReceiverRoot ::=
<FromBasic> <FromBasic>
......
package org.jastadd.ragconnect.tests; package org.jastadd.ragconnect.tests;
import attribute.ast.*; import attributeInc.ast.*;
import de.tudresden.inf.st.jastadd.dumpAst.ast.Dumper;
import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Tag;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import static java.util.function.Predicate.isEqual;
import static org.awaitility.Awaitility.await;
import static org.jastadd.ragconnect.tests.TestUtils.mqttUri;
import static org.jastadd.ragconnect.tests.TestUtils.waitForMqtt;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/** /**
* Test case "attribute". * Test case "attribute".
...@@ -13,27 +26,150 @@ import java.io.IOException; ...@@ -13,27 +26,150 @@ import java.io.IOException;
@Tag("Incremental") @Tag("Incremental")
@Tag("New") @Tag("New")
public class AttributeTest extends AbstractMqttTest { public class AttributeTest extends AbstractMqttTest {
Root model;
MqttHandler handler; private static final String TOPIC_WILDCARD = "attr/#";
private static final String TOPIC_BASIC = "attr/string/basic";
private static final String TOPIC_SIMPLE_NO_MAPPING = "attr/string/simple/plain";
private static final String TOPIC_SIMPLE_WITH_MAPPING = "attr/string/simple/mapped";
private static final String TOPIC_TRANSFORMED_NO_MAPPING = "attr/int/transformed/plain";
private static final String TOPIC_TRANSFORMED_WITH_MAPPING = "attr/int/transformed/mapped";
private static final String TOPIC_REFERENCE_TYPE_NO_MAPPING = "attr/a/ref/plain";
private static final String TOPIC_REFERENCE_TYPE_WITH_MAPPING = "attr/a/ref/mapped";
private static final String TOPIC_NTA_NO_MAPPING = "attr/a/nta/plain";
private static final String TOPIC_NTA_WITH_MAPPING = "attr/a/nta/mapped";
private static final String INITIAL_STRING = "initial";
private MqttHandler handler;
private ReceiverData data;
private Root model;
private SenderRoot senderString;
private SenderRoot senderInt;
private SenderRoot senderA;
private ReceiverRoot receiverRoot;
@Override @Override
protected void createModel() { protected void createModel() {
model = new Root();
// model.trace().setReceiver(TestUtils::logEvent);
senderString = new SenderRoot().setInput(INITIAL_STRING);
senderInt = new SenderRoot().setInput(INITIAL_STRING);
senderA = new SenderRoot().setInput(INITIAL_STRING);
receiverRoot = new ReceiverRoot();
model.addSenderRoot(senderString);
model.addSenderRoot(senderInt);
model.addSenderRoot(senderA);
model.setReceiverRoot(receiverRoot);
} }
@Override @Override
protected void setupReceiverAndConnect() throws IOException, InterruptedException { protected void setupReceiverAndConnect() throws IOException, InterruptedException {
model.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS);
handler = new MqttHandler().setHost(TestUtils.getMqttHost()).dontSendWelcomeMessage();
assertTrue(handler.waitUntilReady(2, TimeUnit.SECONDS));
data = new ReceiverData();
assertTrue(handler.newConnection(TOPIC_WILDCARD, bytes -> data.numberOfValues += 1));
// connect receive
assertTrue(receiverRoot.connectFromBasic(mqttUri(TOPIC_BASIC)));
assertTrue(receiverRoot.connectFromSimpleNoMapping(mqttUri(TOPIC_SIMPLE_NO_MAPPING)));
assertTrue(receiverRoot.connectFromSimpleWithMapping(mqttUri(TOPIC_SIMPLE_WITH_MAPPING)));
assertTrue(receiverRoot.connectFromTransformedNoMapping(mqttUri(TOPIC_TRANSFORMED_NO_MAPPING)));
assertTrue(receiverRoot.connectFromTransformedWithMapping(mqttUri(TOPIC_TRANSFORMED_WITH_MAPPING)));
assertTrue(receiverRoot.connectFromReferenceTypeNoMapping(mqttUri(TOPIC_REFERENCE_TYPE_NO_MAPPING)));
assertTrue(receiverRoot.connectFromReferenceTypeWithMapping(mqttUri(TOPIC_REFERENCE_TYPE_WITH_MAPPING)));
assertTrue(receiverRoot.connectFromNTANoMapping(mqttUri(TOPIC_NTA_NO_MAPPING)));
assertTrue(receiverRoot.connectFromNTAWithMapping(mqttUri(TOPIC_NTA_WITH_MAPPING)));
// connect send, and wait to receive (if writeCurrentValue is set)
assertTrue(senderString.connectBasic(mqttUri(TOPIC_BASIC), isWriteCurrentValue()));
assertTrue(senderString.connectSimple(mqttUri(TOPIC_SIMPLE_NO_MAPPING), isWriteCurrentValue()));
assertTrue(senderString.connectSimple(mqttUri(TOPIC_SIMPLE_WITH_MAPPING), isWriteCurrentValue()));
assertTrue(senderInt.connectTransformed(mqttUri(TOPIC_TRANSFORMED_NO_MAPPING), isWriteCurrentValue()));
assertTrue(senderInt.connectTransformed(mqttUri(TOPIC_TRANSFORMED_WITH_MAPPING), isWriteCurrentValue()));
assertTrue(senderA.connectToReferenceType(mqttUri(TOPIC_REFERENCE_TYPE_NO_MAPPING), isWriteCurrentValue()));
assertTrue(senderA.connectToReferenceType(mqttUri(TOPIC_REFERENCE_TYPE_WITH_MAPPING), isWriteCurrentValue()));
assertTrue(senderA.connectToNTA(mqttUri(TOPIC_NTA_NO_MAPPING), isWriteCurrentValue()));
assertTrue(senderA.connectToNTA(mqttUri(TOPIC_NTA_WITH_MAPPING), isWriteCurrentValue()));
waitForValue(senderString.basic(), receiverRoot::getFromBasic);
waitForValue(senderString.simple(), receiverRoot::getFromSimpleNoMapping);
waitForNonNull(receiverRoot::getFromReferenceTypeNoMapping);
waitForNonNull(receiverRoot::getFromNTANoMapping);
}
private <T> void waitForValue(T expectedValue, Callable<T> callable) {
if (isWriteCurrentValue()) {
await().until(callable, isEqual(expectedValue));
}
}
private <T> void waitForNonNull(Callable<T> callable) {
if (isWriteCurrentValue()) {
await().until(callable, Predicate.not(isEqual(null)));
}
} }
@Override @Override
protected void communicateSendInitialValue() throws IOException, InterruptedException { protected void communicateSendInitialValue() throws IOException, InterruptedException {
// basic, simple <-- senderString
// transformed <-- senderInt
// ref-type, nta <-- senderA
check(9, INITIAL_STRING, INITIAL_STRING + "Post", INITIAL_STRING, INITIAL_STRING, INITIAL_STRING);
senderString.setInput("test-01");
check(12, "test-01", "test-01Post", INITIAL_STRING, INITIAL_STRING, INITIAL_STRING);
} }
@Override @Override
protected void communicateOnlyUpdatedValue() throws IOException, InterruptedException { protected void communicateOnlyUpdatedValue() throws IOException, InterruptedException {
waitForMqtt();
}
private void check(int numberOfValues, String basic, String simple, String transformed,
String refType, String nta) {
awaitEquals(numberOfValues, () -> data.numberOfValues, "numberOfValues");
try {
Path tempFile = Files.createTempFile("receiverRoot", "yml");
Dumper.read(receiverRoot).dumpAsYaml(tempFile, false);
String content = Files.readString(tempFile);
logger.debug("receiverRoot\n" + content);
} catch (IOException e) {
e.printStackTrace();
}
awaitEquals(basic, receiverRoot::getFromBasic, "basic");
awaitEquals(simple, receiverRoot::getFromSimpleNoMapping, "simple");
awaitEquals(simple + "post", receiverRoot::getFromSimpleWithMapping, "simple mapped");
int transformedLength = transformed.length();
awaitEquals(transformedLength, receiverRoot::getFromTransformedNoMapping, "transformed");
awaitEquals(transformedLength + 1, receiverRoot::getFromTransformedWithMapping, "transformed mapped");
checkA(refType, "1",
receiverRoot.getFromReferenceTypeNoMapping(), "ref-type");
checkA(refType + "post", "inner1",
receiverRoot.getFromReferenceTypeWithMapping(), "ref-type mapped");
checkA(nta, "2",
receiverRoot.getFromNTANoMapping(), "nta");
checkA(nta + "post", "inner2",
receiverRoot.getFromNTAWithMapping(), "nta mapped");
}
private void checkA(String expectedValue, String expectedInner, A actual, String message) {
awaitEquals(expectedValue, actual::getValue, message + " value");
awaitEquals(expectedInner, actual.getInner()::getInnerValue, message + " inner");
}
private <T> void awaitEquals(T expected, Callable<T> actual, String alias) {
await(alias).atMost(1500, TimeUnit.MILLISECONDS).until(actual, isEqual(expected));
} }
@Override @Override
...@@ -45,4 +181,8 @@ public class AttributeTest extends AbstractMqttTest { ...@@ -45,4 +181,8 @@ public class AttributeTest extends AbstractMqttTest {
model.ragconnectCloseConnections(); model.ragconnectCloseConnections();
} }
} }
private static class ReceiverData {
int numberOfValues = 0;
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment