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

Merge branch '38-feature-send-endpoint-for-attributes' into 'dev'

Resolve "Feature: Send endpoint for attributes"

Closes #38

See merge request !25
parents 81c522ef c16a42ac
Branches
No related tags found
3 merge requests!39Version 1.1.0,!35Version 1.0.0,!25Resolve "Feature: Send endpoint for attributes"
Pipeline #12565 passed
Root ::= SenderRoot* ReceiverRoot;
SenderRoot ::= <Input> ;
ReceiverRoot ::=
<FromBasic>
<FromSimpleNoMapping>
<FromSimpleWithMapping>
<FromTransformedNoMapping:int>
<FromTransformedWithMapping:int>
FromReferenceTypeNoMapping:A
FromReferenceTypeWithMapping:A
FromNTANoMapping:A
FromNTAWithMapping:A ;
A ::= <Value> Inner ;
Inner ::= <InnerValue> ;
...@@ -60,6 +60,15 @@ D.SourceDoubledValue canDependOn D.TargetDoubledValue as DoubledValue ; ...@@ -60,6 +60,15 @@ D.SourceDoubledValue canDependOn D.TargetDoubledValue as DoubledValue ;
D.SourceDoubledValue canDependOn D.TargetDoubledValue as DoubledValue ; D.SourceDoubledValue canDependOn D.TargetDoubledValue as DoubledValue ;
send D.TargetDoubledValue; send D.TargetDoubledValue;
// non-existence of attributes is not checked by RagConnect
send A.nonExistingAttribute(int);
// Already defined endpoints for attributes will be reported, however
send A.nonExistingAttribute(int);
// mappings are not checked, here string would not match
send A.anotherIntAttribute(int) using StringToString;
// --- mapping definitions --- // --- mapping definitions ---
ListToList maps java.util.List<String> list to java.util.List<String> {: ListToList maps java.util.List<String> list to java.util.List<String> {:
return list; return list;
......
...@@ -11,3 +11,5 @@ Standard.connect Line 43, column 1: Endpoint definition already defined for C.Do ...@@ -11,3 +11,5 @@ Standard.connect Line 43, column 1: Endpoint definition already defined for C.Do
Standard.connect Line 44, column 1: Endpoint definition already defined for C.DoubledValue Standard.connect Line 44, column 1: Endpoint definition already defined for C.DoubledValue
Standard.connect Line 55, column 1: The name of a dependency definition must not be equal to a list-node on the source Standard.connect Line 55, column 1: The name of a dependency definition must not be equal to a list-node on the source
Standard.connect Line 60, column 1: Dependency definition already defined for D with name DoubledValue Standard.connect Line 60, column 1: Dependency definition already defined for D with name DoubledValue
Standard.connect Line 64, column 1: Endpoint definition already defined for A.nonExistingAttribute
Standard.connect Line 67, column 1: Endpoint definition already defined for A.nonExistingAttribute
package org.jastadd.ragconnect.tests;
import attributeInc.ast.*;
import org.junit.jupiter.api.Tag;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.function.Supplier;
import static java.util.function.Predicate.isEqual;
import static org.jastadd.ragconnect.tests.TestUtils.*;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Test case "attribute".
*
* @author rschoene - Initial contribution
*/
@Tag("Incremental")
public class AttributeTest extends AbstractMqttTest {
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 static final String INITIAL_STRING_FOR_INT = "1";
private MqttHandler handler;
private ReceiverData data;
private Root model;
private SenderRoot senderString;
private SenderRoot senderInt;
private SenderRoot senderA;
private ReceiverRoot receiverRoot;
@Override
protected void createModel() {
model = new Root();
// model.trace().setReceiver(TestUtils::logEvent);
senderString = new SenderRoot().setInput(INITIAL_STRING);
senderInt = new SenderRoot().setInput(INITIAL_STRING_FOR_INT);
senderA = new SenderRoot().setInput(INITIAL_STRING);
receiverRoot = new ReceiverRoot();
model.addSenderRoot(senderString);
model.addSenderRoot(senderInt);
model.addSenderRoot(senderA);
model.setReceiverRoot(receiverRoot);
}
@Override
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);
waitForValue(senderInt.transformed(), receiverRoot::getFromTransformedNoMapping);
waitForNonNull(receiverRoot::getFromReferenceTypeNoMapping);
waitForNonNull(receiverRoot::getFromNTANoMapping);
}
private <T> void waitForValue(T expectedValue, Callable<T> callable) {
if (isWriteCurrentValue()) {
awaitMqtt().until(callable, isEqual(expectedValue));
}
}
private <T> void waitForNonNull(Callable<T> callable) {
if (isWriteCurrentValue()) {
awaitMqtt().until(callable, Predicate.not(isEqual(null)));
}
}
@Override
protected void communicateSendInitialValue() throws IOException, InterruptedException {
// basic, simple(2) <-- senderString
// transformed(2) <-- senderInt
// ref-type(2), nta(2) <-- senderA
check(9, INITIAL_STRING, INITIAL_STRING + "Post", INITIAL_STRING_FOR_INT, INITIAL_STRING, INITIAL_STRING);
senderString.setInput("test-01");
check(12, "test-01", "test-01Post", INITIAL_STRING_FOR_INT, INITIAL_STRING, INITIAL_STRING);
senderString.setInput("test-01");
check(12, "test-01", "test-01Post", INITIAL_STRING_FOR_INT, INITIAL_STRING, INITIAL_STRING);
senderInt.setInput("20");
check(14, "test-01", "test-01Post", "20", INITIAL_STRING, INITIAL_STRING);
senderA.setInput("test-03");
check(18, "test-01", "test-01Post", "20", "test-03", "test-03");
assertTrue(senderString.disconnectSimple(mqttUri(TOPIC_SIMPLE_NO_MAPPING)));
assertTrue(senderString.disconnectSimple(mqttUri(TOPIC_SIMPLE_WITH_MAPPING)));
senderString.setInput("test-04");
check(19, "test-04", "test-01Post", "20", "test-03", "test-03");
assertTrue(senderA.disconnectToNTA(mqttUri(TOPIC_NTA_NO_MAPPING)));
senderA.setInput("test-05");
check(22, "test-04", "test-01Post", "20", "test-05", "test-03");
}
@Override
protected void communicateOnlyUpdatedValue() throws IOException, InterruptedException {
waitForMqtt();
// basic, simple(2) <-- senderString
// transformed(2) <-- senderInt
// ref-type(2), nta(2) <-- senderA
check(0, null, null, null, null, null);
senderString.setInput("test-01");
check(3, "test-01", "test-01Post", null, null, null);
senderString.setInput("test-01");
check(3, "test-01", "test-01Post", null, null, null);
senderInt.setInput("20");
check(5, "test-01", "test-01Post", "20", null, null);
senderA.setInput("test-03");
check(9, "test-01", "test-01Post", "20", "test-03", "test-03");
assertTrue(senderString.disconnectSimple(mqttUri(TOPIC_SIMPLE_NO_MAPPING)));
assertTrue(senderString.disconnectSimple(mqttUri(TOPIC_SIMPLE_WITH_MAPPING)));
senderString.setInput("test-04");
check(10, "test-04", "test-01Post", "20", "test-03", "test-03");
assertTrue(senderA.disconnectToNTA(mqttUri(TOPIC_NTA_NO_MAPPING)));
senderA.setInput("test-05");
check(13, "test-04", "test-01Post", "20", "test-05", "test-03");
}
private void check(int numberOfValues, String basic, String simple, String transformed,
String a, String ntaNoMapping) {
awaitEquals(numberOfValues, () -> data.numberOfValues, "numberOfValues");
awaitEquals(Objects.requireNonNullElse(basic, ""),
receiverRoot::getFromBasic, "basic");
if (simple != null) {
awaitEquals(simple,
receiverRoot::getFromSimpleNoMapping, "simple");
awaitEquals(simple + "post",
receiverRoot::getFromSimpleWithMapping, "simple mapped");
} else {
awaitEquals("",
receiverRoot::getFromSimpleNoMapping, "simple null");
awaitEquals("",
receiverRoot::getFromSimpleWithMapping, "simple mapped null");
}
if (transformed != null) {
awaitEquals(Integer.parseInt(transformed),
receiverRoot::getFromTransformedNoMapping, "transformed");
awaitEquals(Integer.parseInt(transformed) + 1,
receiverRoot::getFromTransformedWithMapping, "transformed mapped");
} else {
awaitEquals(0,
receiverRoot::getFromTransformedNoMapping, "transformed null");
awaitEquals(0,
receiverRoot::getFromTransformedWithMapping, "transformed mapped null");
}
if (a != null) {
awaitA(a, "1",
receiverRoot.getFromReferenceTypeNoMapping(), "ref-type");
awaitA(a + "post", "inner1",
receiverRoot.getFromReferenceTypeWithMapping(), "ref-type mapped");
awaitA(a + "post", "inner2",
receiverRoot.getFromNTAWithMapping(), "nta mapped");
} else {
awaitNull(receiverRoot::getFromReferenceTypeNoMapping, "manual ref-type null");
awaitNull(receiverRoot::getFromReferenceTypeWithMapping, "ref-type mapped null");
awaitNull(receiverRoot::getFromNTAWithMapping, "nta mapped null");
}
if (ntaNoMapping != null) {
awaitA(ntaNoMapping, "2",
receiverRoot.getFromNTANoMapping(), "nta");
} else {
awaitNull(receiverRoot::getFromNTANoMapping, "nta null");
}
}
private void awaitNull(Supplier<A> actual, String alias) {
awaitMqtt().alias(alias).until(() -> actual.get() == null);
}
private <T> void awaitEquals(T expected, Callable<T> actual, String alias) {
awaitMqtt().alias(alias).until(actual, isEqual(expected));
}
private void awaitA(String expectedValue, String expectedInner, A actual, String message) {
awaitEquals(expectedValue, actual::getValue, message + " value");
awaitEquals(expectedInner, actual.getInner()::getInnerValue, message + " inner");
}
@Override
protected void closeConnections() {
if (handler != null) {
handler.close();
}
if (model != null) {
model.ragconnectCloseConnections();
}
}
private static class ReceiverData {
int numberOfValues = 0;
}
}
package org.jastadd.ragconnect.tests; package org.jastadd.ragconnect.tests;
import forwardingInc.ast.*; import forwardingInc.ast.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.assertj.core.groups.Tuple; import org.assertj.core.groups.Tuple;
import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Tag;
...@@ -14,9 +12,7 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -14,9 +12,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.groups.Tuple.tuple; import static org.assertj.core.groups.Tuple.tuple;
import static org.awaitility.Awaitility.await; import static org.jastadd.ragconnect.tests.TestUtils.*;
import static org.jastadd.ragconnect.tests.TestUtils.mqttUri;
import static org.jastadd.ragconnect.tests.TestUtils.waitForMqtt;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
/** /**
...@@ -183,7 +179,7 @@ public class ForwardingTest extends AbstractMqttTest { ...@@ -183,7 +179,7 @@ public class ForwardingTest extends AbstractMqttTest {
private void waitForValue() { private void waitForValue() {
if (isWriteCurrentValue()) { if (isWriteCurrentValue()) {
await().until(() -> data.valueSentSinceLastCheck.getAndSet(false)); awaitMqtt().until(() -> data.valueSentSinceLastCheck.getAndSet(false));
} }
} }
...@@ -524,10 +520,8 @@ public class ForwardingTest extends AbstractMqttTest { ...@@ -524,10 +520,8 @@ public class ForwardingTest extends AbstractMqttTest {
if (model != null) { if (model != null) {
model.ragconnectCloseConnections(); model.ragconnectCloseConnections();
} }
if (observer != null) {
observer.init(); observer.init();
} }
}
static class Values<T> { static class Values<T> {
T unnamed; T unnamed;
......
...@@ -11,9 +11,7 @@ import java.util.concurrent.TimeUnit; ...@@ -11,9 +11,7 @@ import java.util.concurrent.TimeUnit;
import java.util.function.Predicate; import java.util.function.Predicate;
import static org.assertj.core.groups.Tuple.tuple; import static org.assertj.core.groups.Tuple.tuple;
import static org.awaitility.Awaitility.await; import static org.jastadd.ragconnect.tests.TestUtils.*;
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.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
...@@ -99,7 +97,7 @@ public class IndexedSendTest extends AbstractMqttTest { ...@@ -99,7 +97,7 @@ public class IndexedSendTest extends AbstractMqttTest {
private void waitForValue(Callable<Integer> callable, int expectedValue) { private void waitForValue(Callable<Integer> callable, int expectedValue) {
if (isWriteCurrentValue()) { if (isWriteCurrentValue()) {
await().until(callable, Predicate.isEqual(expectedValue)); awaitMqtt().until(callable, Predicate.isEqual(expectedValue));
} }
} }
......
...@@ -5,6 +5,8 @@ import com.fasterxml.jackson.core.JsonFactory; ...@@ -5,6 +5,8 @@ import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonGenerator;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.awaitility.Awaitility;
import org.awaitility.core.ConditionFactory;
import org.jastadd.ragconnect.compiler.Compiler; import org.jastadd.ragconnect.compiler.Compiler;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
...@@ -24,7 +26,6 @@ import java.util.stream.Collectors; ...@@ -24,7 +26,6 @@ import java.util.stream.Collectors;
import static java.util.Collections.addAll; import static java.util.Collections.addAll;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.util.Lists.newArrayList; import static org.assertj.core.util.Lists.newArrayList;
import static org.awaitility.Awaitility.await;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail;
...@@ -145,6 +146,10 @@ public class TestUtils { ...@@ -145,6 +146,10 @@ public class TestUtils {
TimeUnit.MILLISECONDS.sleep(1500); TimeUnit.MILLISECONDS.sleep(1500);
} }
public static ConditionFactory awaitMqtt() {
return Awaitility.await().atMost(1500, TimeUnit.MILLISECONDS);
}
static <T_Event, T_ASTNode> void logEvent(T_Event event, T_ASTNode node, String attribute, Object params, Object value) { static <T_Event, T_ASTNode> void logEvent(T_Event event, T_ASTNode node, String attribute, Object params, Object value) {
logger.info("event: {}, node: {}, attribute: {}, params: {}, value: {}", logger.info("event: {}, node: {}, attribute: {}, params: {}, value: {}",
event, node, attribute, params, value); event, node, attribute, params, value);
...@@ -388,7 +393,7 @@ public class TestUtils { ...@@ -388,7 +393,7 @@ public class TestUtils {
} }
void awaitChange() { void awaitChange() {
await().until(hasChanged); awaitMqtt().until(hasChanged);
updatePrevious(); updatePrevious();
} }
......
...@@ -14,10 +14,8 @@ import java.util.concurrent.TimeUnit; ...@@ -14,10 +14,8 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function; import java.util.function.Function;
import static org.awaitility.Awaitility.await; import static org.jastadd.ragconnect.tests.TestUtils.*;
import static org.jastadd.ragconnect.tests.TestUtils.IntList.list; import static org.jastadd.ragconnect.tests.TestUtils.IntList.list;
import static org.jastadd.ragconnect.tests.TestUtils.mqttUri;
import static org.jastadd.ragconnect.tests.TestUtils.testJaddContainReferenceToJackson;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
/** /**
...@@ -167,7 +165,7 @@ public abstract class AbstractSingleListTest extends AbstractMqttTest { ...@@ -167,7 +165,7 @@ public abstract class AbstractSingleListTest extends AbstractMqttTest {
private void waitForValue() { private void waitForValue() {
if (isWriteCurrentValue()) { if (isWriteCurrentValue()) {
await().until(() -> data.valueSentSinceLastCheck.getAndSet(false)); awaitMqtt().until(() -> data.valueSentSinceLastCheck.getAndSet(false));
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment