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

working on relations

- begin with test
parent e616deb6
No related branches found
No related tags found
1 merge request!27Resolve "Feature: Send endpoint for relations"
Pipeline #12615 failed
......@@ -657,7 +657,29 @@ task compileAttributeIncremental(type: RagConnectTest) {
extraOptions = JASTADD_INCREMENTAL_OPTIONS_TRACING_FULL
}
}
compileAttributeIncremental.outputs.upToDateWhen { false }
// --- Test: relation-incremental ---
task compileRelationIncremental(type: RagConnectTest) {
ragconnect {
outputDir = file('src/test/02-after-ragconnect/relationInc')
inputFiles = [file('src/test/01-input/relation/Test.relast'),
file('src/test/01-input/relation/Test.connect')]
rootNode = 'Root'
extraOptions = defaultRagConnectOptionsAnd(['--experimental-jastadd-329'])
}
relast {
useJastAddNames = true
grammarName = 'src/test/03-after-relast/relationInc/relationInc'
serializer = 'jackson'
}
jastadd {
jastAddList = 'JastAddList'
packageName = 'relationInc.ast'
inputFiles = [file('src/test/01-input/relation/Test.jadd')]
extraOptions = JASTADD_INCREMENTAL_OPTIONS_TRACING_FULL
}
}
compileRelationIncremental.outputs.upToDateWhen { false }
static ArrayList<String> defaultRagConnectOptionsAnd(ArrayList<String> options = []) {
if (!options.contains('--logTarget=slf4j')) {
......
# Relation
Idea: Use send definitions for relations.
//send SenderRoot.MyA;
//send SenderRoot.OptionalA;
//send SenderRoot.ListA;
//
//send SenderRoot.BiMyA;
//send SenderRoot.BiOptionalA;
//send SenderRoot.BiListA;
//
//send SenderRoot.MyB using ConcatValues;
//send SenderRoot.OptionalB using ConcatValues;
//send SenderRoot.ListB using ConcatValueList;
//
//send SenderRoot.BiMyB using ConcatValues;
//send SenderRoot.BiOptionalB using ConcatValues;
//send SenderRoot.BiListB using ConcatValueList;
ConcatValues maps B b to String {:
return b,getValue() + b.getInner().getInnerValue();
:}
ConcatValueList maps JastAddList<B> list to String {:
StringBuilder sb = new StringBuilder();
for (B b : list) {
sb.append(b,getValue() + b.getInner().getInnerValue()).append(";");
}
return sb.toString();
:}
receive ReceiverRoot.FromMyA;
receive ReceiverRoot.FromOptionalA;
receive ReceiverRoot.FromListA;
receive ReceiverRoot.FromBiMyA;
receive ReceiverRoot.FromBiOptionalA;
receive ReceiverRoot.FromBiListA;
receive ReceiverRoot.FromMyB;
receive ReceiverRoot.FromOptionalB;
receive ReceiverRoot.FromListB;
receive ReceiverRoot.FromBiMyB;
receive ReceiverRoot.FromBiOptionalB;
receive ReceiverRoot.FromBiListB;
aspect Computation {
}
aspect MakeCodeCompile {
}
aspect MakeCodeWork {
public boolean SenderRoot.connectMyA(String uriString, boolean sendCurrentValue) { return true; }
public boolean SenderRoot.connectOptionalA(String uriString, boolean sendCurrentValue) { return true; }
public boolean SenderRoot.connectListA(String uriString, boolean sendCurrentValue) { return true; }
//
public boolean SenderRoot.connectBiMyA(String uriString, boolean sendCurrentValue) { return true; }
public boolean SenderRoot.connectBiOptionalA(String uriString, boolean sendCurrentValue) { return true; }
public boolean SenderRoot.connectBiListA(String uriString, boolean sendCurrentValue) { return true; }
//
public boolean SenderRoot.connectMyB(String uriString, boolean sendCurrentValue) { return true; }
public boolean SenderRoot.connectOptionalB(String uriString, boolean sendCurrentValue) { return true; }
public boolean SenderRoot.connectListB(String uriString, boolean sendCurrentValue) { return true; }
//
public boolean SenderRoot.connectBiMyB(String uriString, boolean sendCurrentValue) { return true; }
public boolean SenderRoot.connectBiOptionalB(String uriString, boolean sendCurrentValue) { return true; }
public boolean SenderRoot.connectBiListB(String uriString, boolean sendCurrentValue) { return true; }
}
aspect NameResolution {
// overriding customID guarantees to produce the same JSON representation for equal lists
// otherwise, the value for id is different each time
@Override
protected String A.customID() {
return getClass().getSimpleName() + getValue();
}
@Override
protected String B.customID() {
return getClass().getSimpleName() + getValue();
}
@Override
protected String Inner.customID() {
return getClass().getSimpleName() + getInnerValue();
}
}
Root ::= SenderRoot* ReceiverRoot;
SenderRoot ::= A* B* ;
rel SenderRoot.MyA -> A;
rel SenderRoot.OptionalA? -> A;
rel SenderRoot.ListA* -> A;
rel SenderRoot.BiMyA <-> A.ToMyA;
rel SenderRoot.BiOptionalA? <-> A.ToOptionalA;
rel SenderRoot.BiListA* <-> A.ToListA;
rel SenderRoot.MyB -> B;
rel SenderRoot.OptionalB? -> B;
rel SenderRoot.ListB* -> B;
rel SenderRoot.BiMyB <-> B.ToMyB;
rel SenderRoot.BiOptionalB? <-> B.ToOptionalB;
rel SenderRoot.BiListB* <-> B.ToListB;
ReceiverRoot ::=
FromMyA:A FromOptionalA:A FromListA:A
FromBiMyA:A FromBiOptionalA:A FromBiListA:A
<FromMyB:String> <FromOptionalB:String> <FromListB:String>
<FromBiMyB:String> <FromBiOptionalB:String> <FromBiListB:String>
;
A ::= <Value> Inner ;
B ::= <Value> Inner ;
Inner ::= <InnerValue> ;
package org.jastadd.ragconnect.tests;
import org.assertj.core.groups.Tuple;
import org.hamcrest.Matchers;
import relationInc.ast.*;
import org.junit.jupiter.api.Tag;
import java.io.IOException;
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.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.jastadd.ragconnect.tests.TestUtils.*;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
/**
* Test case "relation".
*
* @author rschoene - Initial contribution
*/
@Tag("Incremental")
public class RelationTest extends AbstractMqttTest {
private static final String TOPIC_WILDCARD = "rel/#";
private static final String TOPIC_MY_A = "rel/my_a";
private static final String TOPIC_OPTIONAL_A = "rel/optional_a";
private static final String TOPIC_LIST_A = "rel/list_a";
private static final String TOPIC_BI_MY_A = "rel/bi_my_a";
private static final String TOPIC_BI_OPTIONAL_A = "rel/bi_optional_a";
private static final String TOPIC_BI_LIST_A = "rel/bi_list_a";
private static final String TOPIC_MY_B = "rel/my_b";
private static final String TOPIC_OPTIONAL_B = "rel/optional_b";
private static final String TOPIC_LIST_B = "rel/list_b";
private static final String TOPIC_BI_MY_B = "rel/bi_my_b";
private static final String TOPIC_BI_OPTIONAL_B = "rel/bi_optional_b";
private static final String TOPIC_BI_LIST_B = "rel/bi_list_b";
private MqttHandler handler;
private ReceiverData data;
private Root model;
private SenderRoot senderUni;
private SenderRoot senderBi;
private ReceiverRoot receiverRoot;
@Override
protected void createModel() {
model = new Root();
// model.trace().setReceiver(TestUtils::logEvent);
senderUni = new SenderRoot();
A a1 = createA("a1");
senderUni.addA(a1);
senderUni.setMyA(a1);
senderUni.setBiMyA(a1);
senderUni.addA(createA("a2"));
senderUni.addA(createA("a3"));
senderBi = new SenderRoot();
B b1 = createB("b1");
senderUni.addB(b1);
senderUni.setMyB(b1);
senderUni.setBiMyB(b1);
senderUni.addB(createB("b2"));
senderUni.addB(createB("b3"));
receiverRoot = new ReceiverRoot();
model.addSenderRoot(senderUni);
model.addSenderRoot(senderBi);
model.setReceiverRoot(receiverRoot);
}
private A createA(String value) {
return new A().setValue(value)
.setInner(new Inner().setInnerValue("inner" + value));
}
private B createB(String value) {
return new B().setValue(value)
.setInner(new Inner().setInnerValue("inner" + value));
}
@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.connectFromMyA(mqttUri(TOPIC_MY_A)));
assertTrue(receiverRoot.connectFromOptionalA(mqttUri(TOPIC_OPTIONAL_A)));
assertTrue(receiverRoot.connectFromListA(mqttUri(TOPIC_LIST_A)));
assertTrue(receiverRoot.connectFromBiMyA(mqttUri(TOPIC_BI_MY_A)));
assertTrue(receiverRoot.connectFromBiOptionalA(mqttUri(TOPIC_BI_OPTIONAL_A)));
assertTrue(receiverRoot.connectFromBiListA(mqttUri(TOPIC_BI_LIST_A)));
assertTrue(receiverRoot.connectFromMyB(mqttUri(TOPIC_MY_B)));
assertTrue(receiverRoot.connectFromOptionalB(mqttUri(TOPIC_OPTIONAL_B)));
assertTrue(receiverRoot.connectFromListB(mqttUri(TOPIC_LIST_B)));
assertTrue(receiverRoot.connectFromBiMyB(mqttUri(TOPIC_BI_MY_B)));
assertTrue(receiverRoot.connectFromBiOptionalB(mqttUri(TOPIC_BI_OPTIONAL_B)));
assertTrue(receiverRoot.connectFromBiListB(mqttUri(TOPIC_BI_LIST_B)));
// connect send, and wait to receive (if writeCurrentValue is set)
assertTrue(senderUni.connectMyA(mqttUri(TOPIC_MY_A), isWriteCurrentValue()));
assertTrue(senderUni.connectOptionalA(mqttUri(TOPIC_OPTIONAL_A), isWriteCurrentValue()));
assertTrue(senderUni.connectListA(mqttUri(TOPIC_LIST_A), isWriteCurrentValue()));
assertTrue(senderBi.connectBiMyA(mqttUri(TOPIC_BI_MY_A), isWriteCurrentValue()));
assertTrue(senderBi.connectBiOptionalA(mqttUri(TOPIC_BI_OPTIONAL_A), isWriteCurrentValue()));
assertTrue(senderBi.connectBiListA(mqttUri(TOPIC_BI_LIST_A), isWriteCurrentValue()));
assertTrue(senderUni.connectMyB(mqttUri(TOPIC_MY_B), isWriteCurrentValue()));
assertTrue(senderUni.connectOptionalB(mqttUri(TOPIC_OPTIONAL_B), isWriteCurrentValue()));
assertTrue(senderUni.connectListB(mqttUri(TOPIC_LIST_B), isWriteCurrentValue()));
assertTrue(senderBi.connectBiMyB(mqttUri(TOPIC_BI_MY_B), isWriteCurrentValue()));
assertTrue(senderBi.connectBiOptionalB(mqttUri(TOPIC_BI_OPTIONAL_B), isWriteCurrentValue()));
assertTrue(senderBi.connectBiListB(mqttUri(TOPIC_BI_LIST_B), isWriteCurrentValue()));
waitForNonNull(receiverRoot::getFromMyA);
waitForNonNull(receiverRoot::getFromBiMyA);
waitForNonNull(receiverRoot::getFromMyB);
waitForNonNull(receiverRoot::getFromBiMyB);
}
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 {
// TODO implement test
// TODO also check disconnect
}
@Override
protected void communicateOnlyUpdatedValue() throws IOException, InterruptedException {
waitForMqtt();
// TODO implement test
// TODO also check disconnect
}
private void checkAs(int numberOfValues, String myA, String optionalA, Tuple listA,
String biMyA, String biOptionalA, Tuple biListA) {
awaitEquals(numberOfValues, () -> data.numberOfValues, "numberOfValues");
// awaitEquals(Objects.requireNonNullElse(basic, ""),
// receiverRoot::getFromBasic, "basic");
awaitAorNull(myA, receiverRoot::getFromMyA, "myA");
awaitAorNull(optionalA, receiverRoot::getFromOptionalA, "myA");
// TODO compare list
awaitAorNull(biMyA, receiverRoot::getFromBiMyA, "biMyA");
awaitAorNull(biOptionalA, receiverRoot::getFromBiOptionalA, "biMyA");
// TODO compare bi-list
}
// TODO checkBs
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 awaitAorNull(String expectedValue, Callable<A> actual, String alias) {
if (expectedValue == null) {
awaitNull(convertToSupplier(actual), alias + " null");
return;
}
String expectedInner = "inner" + expectedValue;
awaitMqtt().alias(alias).until(actual, Matchers.allOf(
hasProperty("Value", equalTo(expectedValue)),
hasProperty("Inner", hasProperty("InnerValue", equalTo(expectedInner)))));
}
private Supplier<A> convertToSupplier(Callable<A> actual) {
return () -> {
try {
return actual.call();
} catch (Exception e) {
fail(e);
return null;
}
};
}
@Override
protected void closeConnections() {
if (handler != null) {
handler.close();
}
if (model != null) {
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