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

WIP: Working on bugfixes for attributes

- compare params for list NTAs when indexed
- simplify observer add
- add Gradle task to run using parameters.txt (line-separated parameters, with #-comments)
parent 130bc9d1
No related branches found
No related tags found
1 merge request!32Resolve "Allow collection and circular attributes as endpoint targets"
Pipeline #13816 failed
...@@ -3,3 +3,4 @@ src/gen-res/ ...@@ -3,3 +3,4 @@ src/gen-res/
src/gen/ src/gen/
out/ out/
*.class *.class
/parameters.txt
...@@ -187,6 +187,15 @@ ext { ...@@ -187,6 +187,15 @@ ext {
} }
application.mainClassName = "${mainClassName}" application.mainClassName = "${mainClassName}"
task runParameters(type: JavaExec) {
group 'application'
description 'Run using parameters.txt (line-separated with comments)'
classpath sourceSets.main.runtimeClasspath
main = "org.jastadd.ragconnect.compiler.Compiler"
args new File('ragconnect.base/parameters.txt').text.strip().split("\n").dropWhile { it.startsWith("#") }
standardInput = System.in
}
jar { jar {
manifest.attributes "Main-Class": "${mainClassName}" manifest.attributes "Main-Class": "${mainClassName}"
} }
......
...@@ -521,14 +521,14 @@ aspect MustacheSendDefinition { ...@@ -521,14 +521,14 @@ aspect MustacheSendDefinition {
java.util.List<SendIncrementalObserverEntry> result = new java.util.ArrayList<>(); java.util.List<SendIncrementalObserverEntry> result = new java.util.ArrayList<>();
// "{{getterMethodName}}{{#IndexBasedListAccess}}_int{{/IndexBasedListAccess}}" // "{{getterMethodName}}{{#IndexBasedListAccess}}_int{{/IndexBasedListAccess}}"
result.add(SendIncrementalObserverEntry.of(getterMethodName() + (getIndexBasedListAccess() ? "_int" : ""), result.add(SendIncrementalObserverEntry.of(getterMethodName() + (getIndexBasedListAccess() ? "_int" : ""),
getIndexBasedListAccess(), "index")); getIndexBasedListAccess(), getIndexBasedListAccess() ? "index" : "null"));
if (indexBasedAccessAndTargetIsNTA()) { if (indexBasedAccessAndTargetIsNTA()) {
// "{{getterMethodName}}List" // "{{getterMethodName}}List"
result.add(SendIncrementalObserverEntry.of(getterMethodName() + "List", false, "index")); result.add(SendIncrementalObserverEntry.of(getterMethodName() + "List", false, "index"));
} }
if (targetIsAttribute()) { if (targetIsAttribute()) {
// "{{parentTypeName}}_{{getterMethodName}}{{#IndexBasedListAccess}}_int{{/IndexBasedListAccess}}" // "{{parentTypeName}}_{{getterMethodName}}{{#IndexBasedListAccess}}_int{{/IndexBasedListAccess}}"
result.add(SendIncrementalObserverEntry.of(parentTypeName() + "_" + getterMethodName() + (getIndexBasedListAccess() ? "_int" : ""), getIndexBasedListAccess(), "index")); result.add(SendIncrementalObserverEntry.of(parentTypeName() + "_" + getterMethodName() + (getIndexBasedListAccess() ? "_int" : ""), getIndexBasedListAccess(), getIndexBasedListAccess() ? "index" : "null"));
} }
return result; return result;
} }
...@@ -611,10 +611,10 @@ containingEndpointDefinition().getIndexBasedListAccess()); ...@@ -611,10 +611,10 @@ containingEndpointDefinition().getIndexBasedListAccess());
syn String EndpointDefinition.typeName() = type().getName(); syn String EndpointDefinition.typeName() = type().getName();
syn String MEndpointDefinition.typeName() = getEndpointDefinition().typeName(); syn String MEndpointDefinition.typeName() = getEndpointDefinition().typeName();
static SendIncrementalObserverEntry SendIncrementalObserverEntry.of(String attributeString, boolean useParams, Object params) { static SendIncrementalObserverEntry SendIncrementalObserverEntry.of(String attributeString, boolean compareParams, Object params) {
return new SendIncrementalObserverEntry() return new SendIncrementalObserverEntry()
.setParams(useParams ? params : null) .setParams(params)
.setCompareParams(useParams) .setCompareParams(compareParams)
.setAttributeString(attributeString); .setAttributeString(attributeString);
} }
} }
......
...@@ -163,36 +163,17 @@ aspect RagConnectObserver { ...@@ -163,36 +163,17 @@ aspect RagConnectObserver {
node.trace().setReceiver(this); node.trace().setReceiver(this);
} }
void add(RagConnectToken connectToken, ASTNode node, Runnable attributeCall, String... attributeStrings) { void add(RagConnectToken connectToken, ASTNode node, boolean compareParams, Object params,
internal_add(connectToken, node, attributeStrings, false, null, attributeCall); Runnable attributeCall, String attributeString) {
}
void add(RagConnectToken connectToken, ASTNode node, Object params, Runnable attributeCall, String... attributeStrings) {
internal_add(connectToken, node, attributeStrings, true, params, attributeCall);
}
private void internal_add(RagConnectToken connectToken, ASTNode node, String[] attributeStrings,
boolean compareParams, Object params, Runnable attributeCall) {
if (attributeStrings.length == 0) {
{{logWarn}}("No attribute string given to observe for {{log_}}!", connectToken.uri);
}
for (String attributeString : attributeStrings) {
internal_add(connectToken, node, attributeString, compareParams, params, attributeCall);
}
}
private void internal_add(RagConnectToken connectToken, ASTNode node, String attributeString,
boolean compareParams, Object params, Runnable attributeCall) {
{{#configLoggingEnabledForIncremental}} {{#configLoggingEnabledForIncremental}}
{{logDebug}}("** observer add: {{log_}} on {{log_}}{{log_}}", {{logDebug}}("** observer add: {{log_}} on {{log_}}{{log_}}",
node, attributeString, (compareParams ? " (parameterized)" : "")); node, attributeString, (compareParams ? " (parameterized)" : ""));
{{/configLoggingEnabledForIncremental}} {{/configLoggingEnabledForIncremental}}
// either add to an existing entry (with same node, attribute) or create new entry // either add to an existing entry (with same node, attribute, params) or create new entry
//TODO check case, where runnable differs (and baseMembersEqual returns true). need list of runnables, and map<connectToken, runnable> to remove them!
boolean needNewEntry = true; boolean needNewEntry = true;
for (RagConnectObserverEntry entry : observedNodes) { for (RagConnectObserverEntry entry : observedNodes) {
if (entry.baseMembersEqualTo(node, attributeString, true, params)) { if (entry.baseMembersEqualTo(node, attributeString, true, params)) {
entry.connectList.add(connectToken); entry.connectList.add(connectToken);
{{logError}}("baseMembersEqualTo node: {{log_}} atrStr: {{log_}} compare: {{log_}} params: {{log_}}", node, attributeString, compareParams, params);
needNewEntry = false; needNewEntry = false;
break; break;
} }
......
...@@ -68,7 +68,8 @@ public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParamete ...@@ -68,7 +68,8 @@ public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParamete
{{observerInstanceSingletonMethodName}}().add( {{observerInstanceSingletonMethodName}}().add(
connectToken, connectToken,
this, this,
{{#CompareParams}}{{Params}},{{/CompareParams}} {{CompareParams}},
{{Params}},
() -> { () -> {
if (this.{{updateMethodName}}({{#IndexBasedListAccess}}index{{/IndexBasedListAccess}})) { if (this.{{updateMethodName}}({{#IndexBasedListAccess}}index{{/IndexBasedListAccess}})) {
this.{{writeMethodName}}({{#IndexBasedListAccess}}index{{/IndexBasedListAccess}}); this.{{writeMethodName}}({{#IndexBasedListAccess}}index{{/IndexBasedListAccess}});
......
...@@ -3,12 +3,10 @@ package org.jastadd.ragconnect.tests; ...@@ -3,12 +3,10 @@ package org.jastadd.ragconnect.tests;
import indexedSendInc.ast.*; import indexedSendInc.ast.*;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.assertj.core.groups.Tuple; import org.assertj.core.groups.Tuple;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.io.IOException; import java.io.IOException;
import java.util.StringJoiner;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Predicate; import java.util.function.Predicate;
...@@ -25,7 +23,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; ...@@ -25,7 +23,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
* @author rschoene - Initial contribution * @author rschoene - Initial contribution
*/ */
@Tag("Incremental") @Tag("Incremental")
@Tag("New")
public class IndexedSendTest extends AbstractMqttTest { public class IndexedSendTest extends AbstractMqttTest {
private static final String TOPIC_A_MANY_NORMAL_WILDCARD = "a-many/#"; private static final String TOPIC_A_MANY_NORMAL_WILDCARD = "a-many/#";
...@@ -100,27 +97,37 @@ public class IndexedSendTest extends AbstractMqttTest { ...@@ -100,27 +97,37 @@ public class IndexedSendTest extends AbstractMqttTest {
assertTrue(receiverRoot.connectManyAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_WILDCARD))); assertTrue(receiverRoot.connectManyAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_WILDCARD)));
// connect send, and wait to receive (if writeCurrentValue is set) // connect send, and wait to receive (if writeCurrentValue is set)
assertTrue(connectNTAsInstead ? assertConnectAOrMultipleA(TOPIC_A_MANY_NORMAL_0, 0);
senderRoot.connectA(mqttUri(TOPIC_A_MANY_NORMAL_0), 0, isWriteCurrentValue()) :
senderRoot.connectMultipleA(mqttUri(TOPIC_A_MANY_NORMAL_0), 0, isWriteCurrentValue()));
waitForValue(receiverRoot::getNumManyA, 1); waitForValue(receiverRoot::getNumManyA, 1);
assertTrue(connectNTAsInstead ? assertConnectAOrMultipleA(TOPIC_A_MANY_NORMAL_1, 1);
senderRoot.connectA(mqttUri(TOPIC_A_MANY_NORMAL_1), 1, isWriteCurrentValue()) :
senderRoot.connectMultipleA(mqttUri(TOPIC_A_MANY_NORMAL_1), 1, isWriteCurrentValue()));
waitForValue(receiverRoot::getNumManyA, 2); waitForValue(receiverRoot::getNumManyA, 2);
assertTrue(connectNTAsInstead ? assertConnectComputedAOrMultipleAWithSuffix(TOPIC_A_MANY_SUFFIX_0, 0);
senderRoot.connectComputedA(mqttUri(TOPIC_A_MANY_SUFFIX_0), 0, isWriteCurrentValue()) :
senderRoot.connectMultipleAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_0), 0, isWriteCurrentValue()));
waitForValue(receiverRoot::getNumManyAWithSuffix, 1); waitForValue(receiverRoot::getNumManyAWithSuffix, 1);
assertTrue(connectNTAsInstead ? assertConnectComputedAOrMultipleAWithSuffix(TOPIC_A_MANY_SUFFIX_1, 1);
senderRoot.connectComputedA(mqttUri(TOPIC_A_MANY_SUFFIX_1), 1, isWriteCurrentValue()) :
senderRoot.connectMultipleAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_1), 1, isWriteCurrentValue()));
waitForValue(receiverRoot::getNumManyAWithSuffix, 2); waitForValue(receiverRoot::getNumManyAWithSuffix, 2);
} }
private void assertConnectAOrMultipleA(String topic, int index) throws IOException {
assertTrue(connectNTAsInstead ?
senderRoot.connectA(mqttUri(topic), index, isWriteCurrentValue()) :
senderRoot.connectMultipleA(mqttUri(topic), index, isWriteCurrentValue()));
}
private void assertConnectComputedAOrMultipleAWithSuffix(String topic, int index) throws IOException {
assertTrue(connectNTAsInstead ?
senderRoot.connectComputedA(mqttUri(topic), index, isWriteCurrentValue()) :
senderRoot.connectMultipleAWithSuffix(mqttUri(topic), index, isWriteCurrentValue()));
}
private void assertDisconnectComputedAOrMultipleAWithSuffix(String topic) throws IOException {
assertTrue(connectNTAsInstead ?
senderRoot.disconnectComputedA(mqttUri(topic)) :
senderRoot.disconnectMultipleAWithSuffix(mqttUri(topic)));
}
private void checkList(String name, Tuple expected, Supplier<JastAddList<A>> actual) { private void checkList(String name, Tuple expected, Supplier<JastAddList<A>> actual) {
Assertions.assertThat(actual.get()).extracting("Value") Assertions.assertThat(actual.get()).extracting("Value")
.as(name) .as(name)
...@@ -199,13 +206,10 @@ public class IndexedSendTest extends AbstractMqttTest { ...@@ -199,13 +206,10 @@ public class IndexedSendTest extends AbstractMqttTest {
.put(CHECK_MANY_A, manyAtIndex1 != null ? tuple("changedValue", manyAtIndex1) : tuple("changedValue")) .put(CHECK_MANY_A, manyAtIndex1 != null ? tuple("changedValue", manyAtIndex1) : tuple("changedValue"))
.check(); .check();
if (!connectNTAsInstead) { return; } // TODO remove after testing NTAs is complete
// setting same value must not change data, and must not trigger a new sent message // setting same value must not change data, and must not trigger a new sent message
listA0.setValue("changedValue"); listA0.setValue("changedValue");
checker.check(); checker.check();
logger.error(prettyPrint(senderRoot.getAList()));
listA1.setValue(""); listA1.setValue("");
checker.incNumberOfValues().put(CHECK_MANY_A, tuple("changedValue", "")).check(); checker.incNumberOfValues().put(CHECK_MANY_A, tuple("changedValue", "")).check();
...@@ -216,26 +220,39 @@ public class IndexedSendTest extends AbstractMqttTest { ...@@ -216,26 +220,39 @@ public class IndexedSendTest extends AbstractMqttTest {
.check(); .check();
// adding a new element does not automatically send it // adding a new element does not automatically send it
A listA3InSuffix = createA("out"); A listA2InSuffix = createA("out");
senderRoot.addMultipleAWithSuffix(listA3InSuffix); senderRoot.addMultipleAWithSuffix(listA2InSuffix);
checker.check(); checker.check();
// only after connecting it, the element gets sent // only after connecting it, the element gets sent (for SendInitialValue case)
assertTrue(senderRoot.connectMultipleAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_2), 2, true)); assertConnectComputedAOrMultipleAWithSuffix(TOPIC_A_MANY_SUFFIX_2, 2);
if (isWriteCurrentValue()) {
checker.incNumberOfValues() checker.incNumberOfValues()
.put(CHECK_WITH_SUFFIX, suffixAtIndex0 != null ? tuple(suffixAtIndex0, "repost", "outpost") : tuple("repost", "outpost")) .put(CHECK_WITH_SUFFIX, suffixAtIndex0 != null ? tuple(suffixAtIndex0, "repost", "outpost") : tuple("repost", "outpost"));
.check(); }
checker.check();
// after successful disconnect, no messages will be sent // changing the value of the newly added element will send it
assertTrue(senderRoot.disconnectMultipleAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_0))); listA2InSuffix.setValue("goal");
checker.incNumberOfValues()
.put(CHECK_WITH_SUFFIX, suffixAtIndex0 != null ? tuple(suffixAtIndex0, "repost", "goalpost") : tuple("repost", "goalpost"));
checker.check();
// after successful disconnect for index 0, no messages will be sent
assertDisconnectComputedAOrMultipleAWithSuffix(TOPIC_A_MANY_SUFFIX_0);
listA0InSuffix.setValue("willBeIgnored"); listA0InSuffix.setValue("willBeIgnored");
checker.check(); checker.check();
}
private String prettyPrint(JastAddList<A> aList) { // for index 1 (not disconnected), messages will be sent still
StringJoiner sj = new StringJoiner(", ", "[", "]"); listA1InSuffix.setValue("sign");
aList.forEach(a -> sj.add(a.getValue() + "(" + a.getInner().getInnerValue() + ")")); checker.incNumberOfValues()
return sj.toString(); .put(CHECK_WITH_SUFFIX, suffixAtIndex0 != null ? tuple(suffixAtIndex0, "signpost", "goalpost") : tuple("signpost", "goalpost"))
.check();
// after successful disconnect for index 1, no messages will be sent anymore
assertDisconnectComputedAOrMultipleAWithSuffix(TOPIC_A_MANY_SUFFIX_1);
listA1InSuffix.setValue("willBeIgnored");
checker.check();
} }
@Override @Override
......
...@@ -27,9 +27,7 @@ import java.util.function.Predicate; ...@@ -27,9 +27,7 @@ import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
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.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;
...@@ -99,6 +97,12 @@ public class TestUtils { ...@@ -99,6 +97,12 @@ public class TestUtils {
return outPath; return outPath;
} }
public static <T> String prettyPrint(Iterable<T> aList, Function<T, String> elementPrinter) {
StringJoiner sj = new StringJoiner(", ", "[", "]");
aList.forEach(element -> sj.add(elementPrinter.apply(element)));
return sj.toString();
}
public static void assertLinesMatch(String directory, String expectedName, String out) throws IOException { public static void assertLinesMatch(String directory, String expectedName, String out) throws IOException {
Path expectedPath = Paths.get(TestUtils.INPUT_DIRECTORY_PREFIX) Path expectedPath = Paths.get(TestUtils.INPUT_DIRECTORY_PREFIX)
.resolve(directory) .resolve(directory)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment