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

WIP: Working on bugfixes for attributes

- parse complete JavaUse as type for attribute targets
- add new observer entries (inc. eval) for NTA and attribute targets
- tests currently not passing
parent fe5bffe0
No related branches found
No related tags found
1 merge request!32Resolve "Allow collection and circular attributes as endpoint targets"
Pipeline #13781 failed
Showing
with 310 additions and 100 deletions
...@@ -34,7 +34,7 @@ dependencies { ...@@ -34,7 +34,7 @@ dependencies {
relast group: 'org.jastadd', name: 'relast', version: "0.3.0-137" relast group: 'org.jastadd', name: 'relast', version: "0.3.0-137"
implementation group: 'org.jastadd', name: 'relast-preprocessor', version: "${preprocessor_version}" implementation group: 'org.jastadd', name: 'relast-preprocessor', version: "${preprocessor_version}"
implementation group: 'com.github.spullara.mustache.java', name: 'compiler', version: "${mustache_java_version}" implementation group: 'com.github.spullara.mustache.java', name: 'compiler', version: "${mustache_java_version}"
runtimeOnly group: 'org.jastadd', name: 'jastadd2', version: '2.3.5-dresden' jastadd2 group: 'org.jastadd', name: 'jastadd2', version: '2.3.5-dresden'
api group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11' api group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
} }
......
...@@ -506,13 +506,36 @@ aspect MustacheSendDefinition { ...@@ -506,13 +506,36 @@ aspect MustacheSendDefinition {
syn String EndpointDefinition.forwardingNTA_Name() = getEndpointTarget().forwardingNTA_Name(); syn String EndpointDefinition.forwardingNTA_Name() = getEndpointTarget().forwardingNTA_Name();
syn String EndpointDefinition.forwardingNTA_Type() = getEndpointTarget().forwardingNTA_Type(); syn String EndpointDefinition.forwardingNTA_Type() = getEndpointTarget().forwardingNTA_Type();
syn boolean EndpointDefinition.targetIsAttribute() = getEndpointTarget().isAttributeEndpointTarget();
syn boolean EndpointDefinition.indexBasedAccessAndTargetIsNTA() {
return typeIsList() && getIndexBasedListAccess() && !needForwardingNTA();
}
syn boolean EndpointDefinition.relationEndpointWithListRole() = getEndpointTarget().relationEndpointWithListRole(); syn boolean EndpointDefinition.relationEndpointWithListRole() = getEndpointTarget().relationEndpointWithListRole();
syn String EndpointDefinition.senderName() = getEndpointTarget().senderName(); syn String EndpointDefinition.senderName() = getEndpointTarget().senderName();
syn java.util.List<SendIncrementalObserverEntry> EndpointDefinition.sendIncrementalObserverEntries() {
// todo maybe getterMethodName needs to be change for indexed send
java.util.List<SendIncrementalObserverEntry> result = new java.util.ArrayList<>();
// "{{getterMethodName}}{{#IndexBasedListAccess}}_int{{/IndexBasedListAccess}}"
result.add(SendIncrementalObserverEntry.of(getterMethodName() + (getIndexBasedListAccess() ? "_int" : ""),
getIndexBasedListAccess(), "index"));
if (indexBasedAccessAndTargetIsNTA()) {
// "{{getterMethodName}}List"
result.add(SendIncrementalObserverEntry.of(getterMethodName() + "List", false, "index"));
}
if (targetIsAttribute()) {
// "{{parentTypeName}}_{{getterMethodName}}{{#IndexBasedListAccess}}_int{{/IndexBasedListAccess}}"
result.add(SendIncrementalObserverEntry.of(parentTypeName() + "_" + getterMethodName() + (getIndexBasedListAccess() ? "_int" : ""), getIndexBasedListAccess(), "index"));
}
return result;
}
syn boolean EndpointDefinition.shouldNotResetValue() = getSend() && !getEndpointTarget().hasAttributeResetMethod(); syn boolean EndpointDefinition.shouldNotResetValue() = getSend() && !getEndpointTarget().hasAttributeResetMethod();
syn String EndpointDefinition.tokenResetMethodName() = getterMethodName() + "_reset"; syn String EndpointDefinition.tokenResetMethodName() = getEndpointTarget().tokenResetMethodName();
syn String EndpointDefinition.updateMethodName() = toMustache().updateMethodName(); syn String EndpointDefinition.updateMethodName() = toMustache().updateMethodName();
...@@ -552,6 +575,9 @@ containingEndpointDefinition().getIndexBasedListAccess()); ...@@ -552,6 +575,9 @@ containingEndpointDefinition().getIndexBasedListAccess());
syn String EndpointTarget.senderName() = ragconnect().internalRagConnectPrefix() + "_sender_" + entityName(); syn String EndpointTarget.senderName() = ragconnect().internalRagConnectPrefix() + "_sender_" + entityName();
eq ContextFreeTypeEndpointTarget.senderName() = null; eq ContextFreeTypeEndpointTarget.senderName() = null;
syn String EndpointTarget.tokenResetMethodName() = getterMethodName() + (
typeIsList() && containingEndpointDefinition().getIndexBasedListAccess() ? "List" : "") + "_reset";
syn String MEndpointDefinition.updateMethodName(); syn String MEndpointDefinition.updateMethodName();
syn String MEndpointDefinition.writeMethodName(); syn String MEndpointDefinition.writeMethodName();
...@@ -584,6 +610,13 @@ containingEndpointDefinition().getIndexBasedListAccess()); ...@@ -584,6 +610,13 @@ 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) {
return new SendIncrementalObserverEntry()
.setParams(useParams ? params : null)
.setCompareParams(useParams)
.setAttributeString(attributeString);
}
} }
aspect MustacheTokenComponent { aspect MustacheTokenComponent {
......
...@@ -15,3 +15,5 @@ MContextFreeTypeSendDefinition : MContextFreeTypeEndpointDefinition; ...@@ -15,3 +15,5 @@ MContextFreeTypeSendDefinition : MContextFreeTypeEndpointDefinition;
MInnerMappingDefinition; MInnerMappingDefinition;
rel MInnerMappingDefinition.MappingDefinition -> MappingDefinition; rel MInnerMappingDefinition.MappingDefinition -> MappingDefinition;
SendIncrementalObserverEntry ::= <Params:Object> <CompareParams:boolean> <AttributeString>;
...@@ -63,8 +63,8 @@ EndpointDefinition endpoint_definition_type ...@@ -63,8 +63,8 @@ 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 BRACKET_LEFT ID.attribute_type_name BRACKET_RIGHT | ID.type_name DOT ID.child_name BRACKET_LEFT java_type_use.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.prettyPrint(), true); :}
| ID.type_name {: return new UntypedEndpointTarget(type_name, "", false); :} | ID.type_name {: return new UntypedEndpointTarget(type_name, "", false); :}
; ;
......
...@@ -110,6 +110,7 @@ aspect RagConnectObserver { ...@@ -110,6 +110,7 @@ aspect RagConnectObserver {
final boolean compareParams; final boolean compareParams;
final Object params; final Object params;
final Runnable attributeCall; final Runnable attributeCall;
//final RagConnectToken connectToken;
final java.util.List<RagConnectToken> connectList = new java.util.ArrayList<>(); final java.util.List<RagConnectToken> connectList = new java.util.ArrayList<>();
RagConnectObserverEntry(ASTNode node, String attributeString, RagConnectObserverEntry(ASTNode node, String attributeString,
...@@ -126,11 +127,11 @@ aspect RagConnectObserver { ...@@ -126,11 +127,11 @@ aspect RagConnectObserver {
} }
boolean baseMembersEqualTo(ASTNode otherNode, String otherAttributeString, boolean baseMembersEqualTo(ASTNode otherNode, String otherAttributeString,
boolean otherCompareParams, Object otherParams) { boolean forceCompareParams, Object otherParams) {
return this.node.equals(otherNode) && return this.node.equals(otherNode) &&
this.attributeString.equals(otherAttributeString) && this.attributeString.equals(otherAttributeString) &&
this.compareParams == otherCompareParams && //this.compareParams == otherCompareParams &&
(!this.compareParams || java.util.Objects.equals(this.params, otherParams)); (!(this.compareParams || forceCompareParams) || java.util.Objects.equals(this.params, otherParams));
} }
} }
...@@ -162,11 +163,21 @@ aspect RagConnectObserver { ...@@ -162,11 +163,21 @@ aspect RagConnectObserver {
node.trace().setReceiver(this); node.trace().setReceiver(this);
} }
void add(RagConnectToken connectToken, ASTNode node, String attributeString, Runnable attributeCall) { void add(RagConnectToken connectToken, ASTNode node, Runnable attributeCall, String... attributeStrings) {
internal_add(connectToken, node, attributeString, false, null, attributeCall); internal_add(connectToken, node, attributeStrings, false, null, attributeCall);
}
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);
} }
void add(RagConnectToken connectToken, ASTNode node, String attributeString, Object params, Runnable attributeCall) {
internal_add(connectToken, node, attributeString, true, params, attributeCall);
} }
private void internal_add(RagConnectToken connectToken, ASTNode node, String attributeString, private void internal_add(RagConnectToken connectToken, ASTNode node, String attributeString,
...@@ -176,10 +187,12 @@ aspect RagConnectObserver { ...@@ -176,10 +187,12 @@ aspect RagConnectObserver {
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) 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, compareParams, 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;
} }
...@@ -193,16 +206,14 @@ aspect RagConnectObserver { ...@@ -193,16 +206,14 @@ aspect RagConnectObserver {
} }
void remove(RagConnectToken connectToken) { void remove(RagConnectToken connectToken) {
RagConnectObserverEntry entryToDelete = null; java.util.List<RagConnectObserverEntry> entriesToDelete = new java.util.ArrayList<>();
for (RagConnectObserverEntry entry : observedNodes) { for (RagConnectObserverEntry entry : observedNodes) {
entry.connectList.remove(connectToken); entry.connectList.remove(connectToken);
if (entry.connectList.isEmpty()) { if (entry.connectList.isEmpty()) {
entryToDelete = entry; entriesToDelete.add(entry);
}
} }
if (entryToDelete != null) {
observedNodes.remove(entryToDelete);
} }
observedNodes.removeAll(entriesToDelete);
} }
@Override @Override
...@@ -256,7 +267,7 @@ aspect RagConnectObserver { ...@@ -256,7 +267,7 @@ aspect RagConnectObserver {
{{/configLoggingEnabledForIncremental}} {{/configLoggingEnabledForIncremental}}
// iterate through list, if matching pair. could maybe be more efficient. // iterate through list, if matching pair. could maybe be more efficient.
for (RagConnectObserverEntry entry : observedNodes) { for (RagConnectObserverEntry entry : observedNodes) {
if (entry.node.equals(node) && entry.attributeString.equals(attribute) && (!entry.compareParams || java.util.Objects.equals(entry.params, params))) { if (entry.baseMembersEqualTo(node, attribute, false, params)) {
// hit. call the attribute/nta-token // hit. call the attribute/nta-token
{{#configLoggingEnabledForIncremental}} {{#configLoggingEnabledForIncremental}}
{{logDebug}}("** observer hit: {{log_}} on {{log_}}", entry.node, entry.attributeString); {{logDebug}}("** observer hit: {{log_}} on {{log_}}", entry.node, entry.attributeString);
......
...@@ -28,6 +28,7 @@ public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParamete ...@@ -28,6 +28,7 @@ public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParamete
final String topic = {{attributeName}}().extractTopic(uri); final String topic = {{attributeName}}().extractTopic(uri);
{{senderName}}.add(() -> { {{senderName}}.add(() -> {
{{#configLoggingEnabledForWrites}} {{#configLoggingEnabledForWrites}}
{{!FIXME circular computation for collection attributes!!}}
{{logDebug}}("[Send] {{entityName}} = {{log_}} -> {{log_}}", {{getterMethodCall}}, {{connectParameterName}}); {{logDebug}}("[Send] {{entityName}} = {{log_}} -> {{log_}}", {{getterMethodCall}}, {{connectParameterName}});
{{/configLoggingEnabledForWrites}} {{/configLoggingEnabledForWrites}}
if ({{lastValueGetterCall}} != null) { if ({{lastValueGetterCall}} != null) {
...@@ -63,18 +64,19 @@ public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParamete ...@@ -63,18 +64,19 @@ public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParamete
if (success) { if (success) {
connectTokenMap.add(this, false, connectToken); connectTokenMap.add(this, false, connectToken);
{{#configIncrementalOptionActive}} {{#configIncrementalOptionActive}}
{{!todo maybe getterMethodName needs to be change for indexed send}} {{#sendIncrementalObserverEntries}}
{{observerInstanceSingletonMethodName}}().add( {{observerInstanceSingletonMethodName}}().add(
connectToken, connectToken,
this, this,
"{{getterMethodName}}{{#IndexBasedListAccess}}_int{{/IndexBasedListAccess}}", {{#CompareParams}}{{Params}},{{/CompareParams}}
{{#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}});
} }
} },
"{{AttributeString}}"
); );
{{/sendIncrementalObserverEntries}}
{{/configIncrementalOptionActive}} {{/configIncrementalOptionActive}}
} }
return success; return success;
......
...@@ -46,7 +46,7 @@ dependencies { ...@@ -46,7 +46,7 @@ dependencies {
ragconnect project(':ragconnect.base') ragconnect project(':ragconnect.base')
testImplementation project(':ragconnect.base') testImplementation project(':ragconnect.base')
implementation group: 'org.jastadd', name: 'jastadd2', version: '2.3.5-dresden-5' implementation group: 'org.jastadd', name: 'jastadd2', version: '2.3.5-dresden-7'
relast group: 'org.jastadd', name: 'relast', version: "0.3.0-137" relast group: 'org.jastadd', name: 'relast', version: "0.3.0-137"
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.4.0' testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.4.0'
......
...@@ -3,6 +3,8 @@ send SenderRoot.simple(String) ; ...@@ -3,6 +3,8 @@ 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) ;
send SenderRoot.circularAttribute(int);
send SenderRoot.collectionAttribute(Set<String>) using SetToString;
AddSuffix maps A a to A {: AddSuffix maps A a to A {:
A result = new A(); A result = new A();
...@@ -20,6 +22,10 @@ AddPlusOne maps int i to int {: ...@@ -20,6 +22,10 @@ AddPlusOne maps int i to int {:
return i + 1; return i + 1;
:} :}
SetToString maps Set<String> set to String {:
return set.toString();
:}
receive ReceiverRoot.FromBasic; receive ReceiverRoot.FromBasic;
receive ReceiverRoot.FromSimpleNoMapping; receive ReceiverRoot.FromSimpleNoMapping;
receive ReceiverRoot.FromSimpleWithMapping using AddStringSuffix; receive ReceiverRoot.FromSimpleWithMapping using AddStringSuffix;
...@@ -29,3 +35,7 @@ receive ReceiverRoot.FromReferenceTypeNoMapping; ...@@ -29,3 +35,7 @@ receive ReceiverRoot.FromReferenceTypeNoMapping;
receive ReceiverRoot.FromReferenceTypeWithMapping using AddSuffix; receive ReceiverRoot.FromReferenceTypeWithMapping using AddSuffix;
receive ReceiverRoot.FromNTANoMapping; receive ReceiverRoot.FromNTANoMapping;
receive ReceiverRoot.FromNTAWithMapping using AddSuffix; receive ReceiverRoot.FromNTAWithMapping using AddSuffix;
receive ReceiverRoot.FromCircularNoMapping;
receive ReceiverRoot.FromCircularWithMapping using AddPlusOne;
receive ReceiverRoot.FromCollectionNoMapping;
receive ReceiverRoot.FromCollectionWithMapping using AddStringSuffix;
import java.util.Set;
import java.util.HashSet;
aspect Computation { aspect Computation {
syn String SenderRoot.basic() = getInput(); syn String SenderRoot.basic() = getInput();
syn String SenderRoot.simple() = getInput() + "Post"; syn String SenderRoot.simple() = getInput() + "Post";
...@@ -18,6 +20,12 @@ aspect Computation { ...@@ -18,6 +20,12 @@ aspect Computation {
result.setInner(inner); result.setInner(inner);
return result; return result;
} }
syn int SenderRoot.circularAttribute() circular [0] {
return Integer.parseInt(getInput()) + 2;
}
coll Set<String> SenderRoot.collectionAttribute() [new HashSet<>()] root SenderRoot ;
A contributes getValue() to SenderRoot.collectionAttribute();
SenderRoot contributes nta toNTA() to SenderRoot.collectionAttribute();
} }
aspect MakeCodeCompile { aspect MakeCodeCompile {
......
Root ::= SenderRoot* ReceiverRoot; Root ::= SenderRoot* ReceiverRoot;
SenderRoot ::= <Input> ; SenderRoot ::= <Input> A* ;
ReceiverRoot ::= ReceiverRoot ::=
<FromBasic> <FromBasic>
<FromSimpleNoMapping> <FromSimpleNoMapping>
...@@ -9,6 +9,10 @@ ReceiverRoot ::= ...@@ -9,6 +9,10 @@ ReceiverRoot ::=
FromReferenceTypeNoMapping:A FromReferenceTypeNoMapping:A
FromReferenceTypeWithMapping:A FromReferenceTypeWithMapping:A
FromNTANoMapping:A FromNTANoMapping:A
FromNTAWithMapping:A ; FromNTAWithMapping:A
<FromCircularNoMapping:int>
<FromCircularWithMapping:int>
<FromCollectionNoMapping>
<FromCollectionWithMapping> ;
A ::= <Value> Inner ; A ::= <Value> Inner ;
Inner ::= <InnerValue> ; Inner ::= <InnerValue> ;
send indexed SenderRoot.MultipleA; send indexed SenderRoot.MultipleA;
send indexed SenderRoot.MultipleAWithSuffix using AddSuffix; send indexed SenderRoot.MultipleAWithSuffix using AddSuffix;
send indexed SenderRoot.A;
send indexed SenderRoot.ComputedA using AddSuffix;
AddSuffix maps A a to A {: AddSuffix maps A a to A {:
A result = new A(); A result = new A();
...@@ -12,3 +13,5 @@ AddSuffix maps A a to A {: ...@@ -12,3 +13,5 @@ AddSuffix maps A a to A {:
receive indexed ReceiverRoot.ManyA; receive indexed ReceiverRoot.ManyA;
receive indexed ReceiverRoot.ManyAWithSuffix; receive indexed ReceiverRoot.ManyAWithSuffix;
receive indexed ReceiverRoot.FromNTA;
receive indexed ReceiverRoot.FromNTAWithSuffix;
aspect Computation {
syn JastAddList<A> SenderRoot.getAList() {
JastAddList<A> result = new JastAddList<>();
getMultipleAList().forEach(a -> result.add(a.touchedTerminals()));
return result;
}
syn JastAddList<A> SenderRoot.getComputedAList() {
JastAddList<A> result = new JastAddList<>();
getMultipleAWithSuffixList().forEach(a -> result.add(a.touchedTerminals()));
return result;
}
A A.touchedTerminals() {
getValue();
getInner().getInnerValue();
return this;
}
}
aspect NameResolution { aspect NameResolution {
// overriding customID guarantees to produce the same JSON representation for equal lists // overriding customID guarantees to produce the same JSON representation for equal lists
// otherwise, the value for id is different each time // otherwise, the value for id is different each time
......
Root ::= SenderRoot ReceiverRoot; Root ::= SenderRoot ReceiverRoot;
SenderRoot ::= MultipleA:A* MultipleAWithSuffix:A* ; SenderRoot ::= MultipleA:A* MultipleAWithSuffix:A* /A*/ /ComputedA:A*/ ;
ReceiverRoot ::= ManyA:A* ManyAWithSuffix:A* ; ReceiverRoot ::= ManyA:A* ManyAWithSuffix:A* FromNTA:A* FromNTAWithSuffix:A* ;
A ::= <Value> Inner ; A ::= <Value> Inner ;
Inner ::= <InnerValue> ; Inner ::= <InnerValue> ;
...@@ -25,7 +25,7 @@ public abstract class AbstractMqttTest extends RagConnectTest { ...@@ -25,7 +25,7 @@ public abstract class AbstractMqttTest extends RagConnectTest {
/** /**
* if the initial/current value shall be sent upon connecting * if the initial/current value shall be sent upon connecting
*/ */
private boolean writeCurrentValue; protected boolean writeCurrentValue;
public boolean isWriteCurrentValue() { public boolean isWriteCurrentValue() {
return writeCurrentValue; return writeCurrentValue;
...@@ -58,7 +58,7 @@ public abstract class AbstractMqttTest extends RagConnectTest { ...@@ -58,7 +58,7 @@ public abstract class AbstractMqttTest extends RagConnectTest {
@Tag("mqtt") @Tag("mqtt")
@RepeatedIfExceptionsTest(repeats = TEST_REPETITIONS) @RepeatedIfExceptionsTest(repeats = TEST_REPETITIONS)
public final void testCommunicateSendInitialValue() throws IOException, InterruptedException { public void testCommunicateSendInitialValue() throws IOException, InterruptedException {
this.writeCurrentValue = true; this.writeCurrentValue = true;
createModel(); createModel();
...@@ -76,7 +76,7 @@ public abstract class AbstractMqttTest extends RagConnectTest { ...@@ -76,7 +76,7 @@ public abstract class AbstractMqttTest extends RagConnectTest {
@Tag("mqtt") @Tag("mqtt")
@RepeatedIfExceptionsTest(repeats = TEST_REPETITIONS) @RepeatedIfExceptionsTest(repeats = TEST_REPETITIONS)
public final void testCommunicateOnlyUpdatedValue() throws IOException, InterruptedException { public void testCommunicateOnlyUpdatedValue() throws IOException, InterruptedException {
this.writeCurrentValue = false; this.writeCurrentValue = false;
createModel(); createModel();
......
...@@ -9,8 +9,10 @@ import java.util.Objects; ...@@ -9,8 +9,10 @@ import java.util.Objects;
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;
import java.util.function.Supplier;
import static java.util.function.Predicate.isEqual; import static java.util.function.Predicate.isEqual;
import static org.assertj.core.api.Assertions.assertThat;
import static org.jastadd.ragconnect.tests.TestUtils.*; import static org.jastadd.ragconnect.tests.TestUtils.*;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
...@@ -20,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.*; ...@@ -20,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.*;
* @author rschoene - Initial contribution * @author rschoene - Initial contribution
*/ */
@Tag("Incremental") @Tag("Incremental")
@Tag("New")
public class AttributeTest extends AbstractMqttTest { public class AttributeTest extends AbstractMqttTest {
private static final String TOPIC_WILDCARD = "attr/#"; private static final String TOPIC_WILDCARD = "attr/#";
...@@ -32,15 +35,22 @@ public class AttributeTest extends AbstractMqttTest { ...@@ -32,15 +35,22 @@ public class AttributeTest extends AbstractMqttTest {
private static final String TOPIC_REFERENCE_TYPE_WITH_MAPPING = "attr/a/ref/mapped"; 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_NO_MAPPING = "attr/a/nta/plain";
private static final String TOPIC_NTA_WITH_MAPPING = "attr/a/nta/mapped"; private static final String TOPIC_NTA_WITH_MAPPING = "attr/a/nta/mapped";
private static final String TOPIC_CIRCULAR_NO_MAPPING = "attr/a/circular/plain";
private static final String TOPIC_CIRCULAR_WITH_MAPPING = "attr/a/circular/mapped";
private static final String TOPIC_COLLECTION_NO_MAPPING = "attr/a/collection/plain";
private static final String TOPIC_COLLECTION_WITH_MAPPING = "attr/a/collection/mapped";
private static final String INITIAL_STRING = "initial"; private static final String INITIAL_STRING = "initial";
private static final String INITIAL_STRING_FOR_INT = "1"; private static final String INITIAL_STRING_FOR_INT = "1";
private static final String INITIAL_STRING_FOR_INT_PLUS_2 = Integer.toString(Integer.parseInt(INITIAL_STRING_FOR_INT) + 2);
private static final String CHECK_BASIC = "basic"; private static final String CHECK_BASIC = "basic";
private static final String CHECK_SIMPLE = "simple"; private static final String CHECK_SIMPLE = "simple";
private static final String CHECK_TRANSFORMED = "transformed"; private static final String CHECK_TRANSFORMED = "transformed";
private static final String CHECK_A = "a"; private static final String CHECK_A = "a";
private static final String CHECK_NTA = "nta"; private static final String CHECK_NTA = "nta";
private static final String CHECK_CIRCULAR = "circular";
private static final String CHECK_COLLECTION = "collection";
private MqttHandler handler; private MqttHandler handler;
private ReceiverData data; private ReceiverData data;
...@@ -82,6 +92,8 @@ public class AttributeTest extends AbstractMqttTest { ...@@ -82,6 +92,8 @@ public class AttributeTest extends AbstractMqttTest {
.setCheckForString(CHECK_TRANSFORMED, this::checkTransformed) .setCheckForString(CHECK_TRANSFORMED, this::checkTransformed)
.setCheckForString(CHECK_A, this::checkA) .setCheckForString(CHECK_A, this::checkA)
.setCheckForString(CHECK_NTA, this::checkNta) .setCheckForString(CHECK_NTA, this::checkNta)
.setCheckForString(CHECK_CIRCULAR, this::checkCircular)
.setCheckForString(CHECK_COLLECTION, this::checkCollection)
; ;
// connect receive // connect receive
...@@ -94,14 +106,22 @@ public class AttributeTest extends AbstractMqttTest { ...@@ -94,14 +106,22 @@ public class AttributeTest extends AbstractMqttTest {
assertTrue(receiverRoot.connectFromReferenceTypeWithMapping(mqttUri(TOPIC_REFERENCE_TYPE_WITH_MAPPING))); assertTrue(receiverRoot.connectFromReferenceTypeWithMapping(mqttUri(TOPIC_REFERENCE_TYPE_WITH_MAPPING)));
assertTrue(receiverRoot.connectFromNTANoMapping(mqttUri(TOPIC_NTA_NO_MAPPING))); assertTrue(receiverRoot.connectFromNTANoMapping(mqttUri(TOPIC_NTA_NO_MAPPING)));
assertTrue(receiverRoot.connectFromNTAWithMapping(mqttUri(TOPIC_NTA_WITH_MAPPING))); assertTrue(receiverRoot.connectFromNTAWithMapping(mqttUri(TOPIC_NTA_WITH_MAPPING)));
assertTrue(receiverRoot.connectFromCircularNoMapping(mqttUri(TOPIC_CIRCULAR_NO_MAPPING)));
assertTrue(receiverRoot.connectFromCircularWithMapping(mqttUri(TOPIC_CIRCULAR_WITH_MAPPING)));
assertTrue(receiverRoot.connectFromCollectionNoMapping(mqttUri(TOPIC_COLLECTION_NO_MAPPING)));
assertTrue(receiverRoot.connectFromCollectionWithMapping(mqttUri(TOPIC_COLLECTION_WITH_MAPPING)));
// connect send, and wait to receive (if writeCurrentValue is set) // connect send, and wait to receive (if writeCurrentValue is set)
assertTrue(senderString.connectBasic(mqttUri(TOPIC_BASIC), isWriteCurrentValue())); assertTrue(senderString.connectBasic(mqttUri(TOPIC_BASIC), isWriteCurrentValue()));
assertTrue(senderString.connectSimple(mqttUri(TOPIC_SIMPLE_NO_MAPPING), isWriteCurrentValue())); assertTrue(senderString.connectSimple(mqttUri(TOPIC_SIMPLE_NO_MAPPING), isWriteCurrentValue()));
assertTrue(senderString.connectSimple(mqttUri(TOPIC_SIMPLE_WITH_MAPPING), isWriteCurrentValue())); assertTrue(senderString.connectSimple(mqttUri(TOPIC_SIMPLE_WITH_MAPPING), isWriteCurrentValue()));
assertTrue(senderString.connectCollectionAttribute(mqttUri(TOPIC_COLLECTION_NO_MAPPING), isWriteCurrentValue()));
assertTrue(senderString.connectCollectionAttribute(mqttUri(TOPIC_COLLECTION_WITH_MAPPING), isWriteCurrentValue()));
assertTrue(senderInt.connectTransformed(mqttUri(TOPIC_TRANSFORMED_NO_MAPPING), isWriteCurrentValue())); assertTrue(senderInt.connectTransformed(mqttUri(TOPIC_TRANSFORMED_NO_MAPPING), isWriteCurrentValue()));
assertTrue(senderInt.connectTransformed(mqttUri(TOPIC_TRANSFORMED_WITH_MAPPING), isWriteCurrentValue())); assertTrue(senderInt.connectTransformed(mqttUri(TOPIC_TRANSFORMED_WITH_MAPPING), isWriteCurrentValue()));
assertTrue(senderInt.connectCircularAttribute(mqttUri(TOPIC_CIRCULAR_NO_MAPPING), isWriteCurrentValue()));
assertTrue(senderInt.connectCircularAttribute(mqttUri(TOPIC_CIRCULAR_WITH_MAPPING), isWriteCurrentValue()));
assertTrue(senderA.connectToReferenceType(mqttUri(TOPIC_REFERENCE_TYPE_NO_MAPPING), isWriteCurrentValue())); assertTrue(senderA.connectToReferenceType(mqttUri(TOPIC_REFERENCE_TYPE_NO_MAPPING), isWriteCurrentValue()));
assertTrue(senderA.connectToReferenceType(mqttUri(TOPIC_REFERENCE_TYPE_WITH_MAPPING), isWriteCurrentValue())); assertTrue(senderA.connectToReferenceType(mqttUri(TOPIC_REFERENCE_TYPE_WITH_MAPPING), isWriteCurrentValue()));
...@@ -111,58 +131,69 @@ public class AttributeTest extends AbstractMqttTest { ...@@ -111,58 +131,69 @@ public class AttributeTest extends AbstractMqttTest {
waitForValue(senderString.basic(), receiverRoot::getFromBasic); waitForValue(senderString.basic(), receiverRoot::getFromBasic);
waitForValue(senderString.simple(), receiverRoot::getFromSimpleNoMapping); waitForValue(senderString.simple(), receiverRoot::getFromSimpleNoMapping);
waitForValue(senderInt.transformed(), receiverRoot::getFromTransformedNoMapping); waitForValue(senderInt.transformed(), receiverRoot::getFromTransformedNoMapping);
waitForNonNull(receiverRoot::getFromCollectionNoMapping);
waitForNonNull(receiverRoot::getFromReferenceTypeNoMapping); waitForNonNull(receiverRoot::getFromReferenceTypeNoMapping);
waitForNonNull(receiverRoot::getFromNTANoMapping); waitForNonNull(receiverRoot::getFromNTANoMapping);
} }
@Override @Override
protected void communicateSendInitialValue() throws IOException, InterruptedException { protected void communicateSendInitialValue() throws IOException, InterruptedException {
// basic, simple(2) <-- senderString // 13 = basic, simple(2), collection(2), transformed(2), circular(2), ref-type(2), nta(2)
// transformed(2) <-- senderInt checker.addToNumberOfValues(13)
// ref-type(2), nta(2) <-- senderA
checker.addToNumberOfValues(9)
.put(CHECK_BASIC, INITIAL_STRING) .put(CHECK_BASIC, INITIAL_STRING)
.put(CHECK_SIMPLE, INITIAL_STRING + "Post") .put(CHECK_SIMPLE, INITIAL_STRING + "Post")
.put(CHECK_TRANSFORMED, INITIAL_STRING_FOR_INT) .put(CHECK_TRANSFORMED, INITIAL_STRING_FOR_INT)
.put(CHECK_A, INITIAL_STRING) .put(CHECK_A, INITIAL_STRING)
.put(CHECK_NTA, INITIAL_STRING); .put(CHECK_NTA, INITIAL_STRING)
.put(CHECK_CIRCULAR, INITIAL_STRING_FOR_INT_PLUS_2)
.put(CHECK_COLLECTION, "[" + INITIAL_STRING + "]");
communicateBoth(); communicateBoth();
} }
@Override @Override
protected void communicateOnlyUpdatedValue() throws IOException, InterruptedException { protected void communicateOnlyUpdatedValue() throws IOException, InterruptedException {
// basic, simple(2) <-- senderString
// transformed(2) <-- senderInt
// ref-type(2), nta(2) <-- senderA
checker.put(CHECK_BASIC, (String) null) checker.put(CHECK_BASIC, (String) null)
.put(CHECK_SIMPLE, (String) null) .put(CHECK_SIMPLE, (String) null)
.put(CHECK_TRANSFORMED, (String) null) .put(CHECK_TRANSFORMED, (String) null)
.put(CHECK_A, (String) null) .put(CHECK_A, (String) null)
.put(CHECK_NTA, (String) null); .put(CHECK_NTA, (String) null)
.put(CHECK_COLLECTION, (String) null);
communicateBoth(); communicateBoth();
} }
private void communicateBoth() throws IOException { private void communicateBoth() throws IOException {
// basic, simple(2), collection(2) <-- senderString
// transformed(2), circular(2) <-- senderInt
// ref-type(2), nta(2) <-- senderA
checker.check(); checker.check();
senderString.setInput("test-01"); senderString.setInput("test-01");
checker.addToNumberOfValues(3) checker.addToNumberOfValues(5) // basic, simple(2), collection(2)
.put(CHECK_BASIC, "test-01") .put(CHECK_BASIC, "test-01")
.put(CHECK_SIMPLE, "test-01Post") .put(CHECK_SIMPLE, "test-01Post")
.put(CHECK_COLLECTION, "[test-01]")
.check(); .check();
// no change for same value
senderString.setInput("test-01"); senderString.setInput("test-01");
checker.check(); checker.check();
// TODO check checks for (circular and) collection
senderString.addA(new A().setValue("test-02").setInner(new Inner().setInnerValue("inner")));
checker.addToNumberOfValues(2) // collection(2)
.put(CHECK_COLLECTION, "[test-01, test-02]")
.check();
senderInt.setInput("20"); senderInt.setInput("20");
checker.addToNumberOfValues(2) checker.addToNumberOfValues(4) // transformed(2), circular(2)
.put(CHECK_TRANSFORMED, "20") .put(CHECK_TRANSFORMED, "20")
.put(CHECK_CIRCULAR, "22")
.check(); .check();
senderA.setInput("test-03"); senderA.setInput("test-03");
checker.addToNumberOfValues(4) checker.addToNumberOfValues(4) // ref-type(2), nta(2)
.put(CHECK_A, "test-03") .put(CHECK_A, "test-03")
.put(CHECK_NTA, "test-03") .put(CHECK_NTA, "test-03")
.check(); .check();
...@@ -170,14 +201,22 @@ public class AttributeTest extends AbstractMqttTest { ...@@ -170,14 +201,22 @@ public class AttributeTest extends AbstractMqttTest {
assertTrue(senderString.disconnectSimple(mqttUri(TOPIC_SIMPLE_NO_MAPPING))); assertTrue(senderString.disconnectSimple(mqttUri(TOPIC_SIMPLE_NO_MAPPING)));
assertTrue(senderString.disconnectSimple(mqttUri(TOPIC_SIMPLE_WITH_MAPPING))); assertTrue(senderString.disconnectSimple(mqttUri(TOPIC_SIMPLE_WITH_MAPPING)));
senderString.setInput("test-04"); senderString.setInput("test-04");
checker.incNumberOfValues() checker.addToNumberOfValues(3) // basic, collection(2)
.put(CHECK_BASIC, "test-04") .put(CHECK_BASIC, "test-04")
.put(CHECK_COLLECTION, "[test-02, test-04]")
.check();
assertTrue(senderString.disconnectCollectionAttribute(mqttUri(TOPIC_COLLECTION_NO_MAPPING)));
assertTrue(senderString.disconnectCollectionAttribute(mqttUri(TOPIC_COLLECTION_WITH_MAPPING)));
senderString.setInput("test-05");
checker.incNumberOfValues() // basic
.put(CHECK_BASIC, "test-05")
.check(); .check();
assertTrue(senderA.disconnectToNTA(mqttUri(TOPIC_NTA_NO_MAPPING))); assertTrue(senderA.disconnectToNTA(mqttUri(TOPIC_NTA_NO_MAPPING)));
senderA.setInput("test-05"); senderA.setInput("test-06");
checker.addToNumberOfValues(3) checker.addToNumberOfValues(3)
.put(CHECK_A, "test-05") .put(CHECK_A, "test-06")
.check(); .check();
} }
...@@ -208,18 +247,17 @@ public class AttributeTest extends AbstractMqttTest { ...@@ -208,18 +247,17 @@ public class AttributeTest extends AbstractMqttTest {
} }
private void checkTransformed(String name, String expected) { private void checkTransformed(String name, String expected) {
_checkInt(name, expected, receiverRoot::getFromTransformedNoMapping, receiverRoot::getFromTransformedWithMapping);
}
private void _checkInt(String name, String expected, Supplier<Integer> noMapping, Supplier<Integer> withMapping) {
if (expected != null) { if (expected != null) {
assertEquals(Integer.parseInt(expected), assertEquals(Integer.parseInt(expected), noMapping.get(), name);
receiverRoot.getFromTransformedNoMapping(), "transformed"); assertEquals(Integer.parseInt(expected) + 1, withMapping.get(), name + " mapped");
assertEquals(Integer.parseInt(expected) + 1,
receiverRoot.getFromTransformedWithMapping(), "transformed mapped");
} else { } else {
assertEquals(0, assertEquals(0, noMapping.get(), name + " null");
receiverRoot.getFromTransformedNoMapping(), "transformed null"); assertEquals(0, withMapping.get(), name + " mapped null");
assertEquals(0,
receiverRoot.getFromTransformedWithMapping(), "transformed mapped null");
} }
} }
private void checkA(String name, String expected) { private void checkA(String name, String expected) {
...@@ -245,6 +283,31 @@ public class AttributeTest extends AbstractMqttTest { ...@@ -245,6 +283,31 @@ public class AttributeTest extends AbstractMqttTest {
} }
} }
private void checkCircular(String name, String expected) {
_checkInt(name, expected, receiverRoot::getFromCircularNoMapping, receiverRoot::getFromCircularWithMapping);
}
private void checkCollection(String name, String expected) {
if (expected != null) {
// TODO probably need to tokenize actual and expected, and compare their elements without order
assertThat(receiverRoot.getFromCollectionWithMapping()).hasSizeGreaterThan(4).endsWith("post");
checkCollectionContent(name, expected, receiverRoot.getFromCollectionNoMapping());
checkCollectionContent(name + " mapped", expected, receiverRoot.getFromCollectionWithMapping().substring(0, receiverRoot.getFromCollectionWithMapping().length() - 4));
} else {
assertEquals("", receiverRoot.getFromCollectionNoMapping(), "collection null");
assertEquals("", receiverRoot.getFromCollectionWithMapping(), "collection mapped null");
}
}
private void checkCollectionContent(String name, String expected, String actual) {
assertThat(actual).as(name)
.startsWith("[")
.endsWith("]");
String[] actualValues = actual.substring(1, actual.length() - 1).split(", ");
String[] expectedValues = expected.substring(1, expected.length() - 1).split(", ");
assertThat(actualValues).containsExactlyInAnyOrder(expectedValues);
}
private void assertA(String expectedValue, String expectedInner, A actual, String message) { private void assertA(String expectedValue, String expectedInner, A actual, String message) {
assertEquals(expectedValue, actual.getValue(), message + " value"); assertEquals(expectedValue, actual.getValue(), message + " value");
assertEquals(expectedInner, actual.getInner().getInnerValue(), message + " inner"); assertEquals(expectedInner, actual.getInner().getInnerValue(), message + " inner");
......
...@@ -2,12 +2,17 @@ package org.jastadd.ragconnect.tests; ...@@ -2,12 +2,17 @@ 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.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Tag;
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;
import java.util.function.Supplier;
import static org.assertj.core.groups.Tuple.tuple; import static org.assertj.core.groups.Tuple.tuple;
import static org.jastadd.ragconnect.tests.TestUtils.*; import static org.jastadd.ragconnect.tests.TestUtils.*;
...@@ -20,6 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; ...@@ -20,6 +25,7 @@ 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/#";
...@@ -33,6 +39,8 @@ public class IndexedSendTest extends AbstractMqttTest { ...@@ -33,6 +39,8 @@ public class IndexedSendTest extends AbstractMqttTest {
private static final String CHECK_MANY_A = "many-a"; private static final String CHECK_MANY_A = "many-a";
private static final String CHECK_WITH_SUFFIX = "many-a-with-suffix"; private static final String CHECK_WITH_SUFFIX = "many-a-with-suffix";
private boolean connectNTAsInstead;
private MqttHandler handler; private MqttHandler handler;
private ReceiverData data; private ReceiverData data;
private TestUtils.TestChecker checker; private TestUtils.TestChecker checker;
...@@ -83,70 +91,91 @@ public class IndexedSendTest extends AbstractMqttTest { ...@@ -83,70 +91,91 @@ public class IndexedSendTest extends AbstractMqttTest {
checker = new TestChecker(); checker = new TestChecker();
checker.setActualNumberOfValues(() -> data.numberOfValues) checker.setActualNumberOfValues(() -> data.numberOfValues)
.setCheckForTuple(CHECK_MANY_A, (name, expected) -> .setCheckForTuple(CHECK_MANY_A, (name, expected) ->
Assertions.assertThat(receiverRoot.getManyAList()).extracting("Value") checkList(name, expected, receiverRoot::getManyAList))
.as(name)
.containsExactlyElementsOf(expected.toList()))
.setCheckForTuple(CHECK_WITH_SUFFIX, (name, expected) -> .setCheckForTuple(CHECK_WITH_SUFFIX, (name, expected) ->
Assertions.assertThat(receiverRoot.getManyAWithSuffixList()).extracting("Value") checkList(name, expected, receiverRoot::getManyAWithSuffixList));
.as(name)
.containsExactlyElementsOf(expected.toList()));
// connect receive // connect receive
assertTrue(receiverRoot.connectManyA(mqttUri(TOPIC_A_MANY_NORMAL_WILDCARD))); assertTrue(receiverRoot.connectManyA(mqttUri(TOPIC_A_MANY_NORMAL_WILDCARD)));
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(senderRoot.connectMultipleA(mqttUri(TOPIC_A_MANY_NORMAL_0), 0, isWriteCurrentValue())); assertTrue(connectNTAsInstead ?
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(senderRoot.connectMultipleA(mqttUri(TOPIC_A_MANY_NORMAL_1), 1, isWriteCurrentValue())); assertTrue(connectNTAsInstead ?
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(senderRoot.connectMultipleAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_0), 0, isWriteCurrentValue())); assertTrue(connectNTAsInstead ?
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(senderRoot.connectMultipleAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_1), 1, isWriteCurrentValue())); assertTrue(connectNTAsInstead ?
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 checkList(String name, Tuple expected, Supplier<JastAddList<A>> actual) {
Assertions.assertThat(actual.get()).extracting("Value")
.as(name)
.containsExactlyElementsOf(expected.toList());
}
private void waitForValue(Callable<Integer> callable, int expectedValue) { private void waitForValue(Callable<Integer> callable, int expectedValue) {
if (isWriteCurrentValue()) { if (isWriteCurrentValue()) {
awaitMqtt().until(callable, Predicate.isEqual(expectedValue)); awaitMqtt().until(callable, Predicate.isEqual(expectedValue));
} }
} }
@Tag("mqtt")
// @RepeatedIfExceptionsTest(repeats = TEST_REPETITIONS)
@Test
public void testCommunicateSendInitialValueWithNTAs() throws IOException, InterruptedException {
this.writeCurrentValue = true;
this.connectNTAsInstead = true;
try {
createModel();
setupReceiverAndConnect();
logger.info("Calling communicateSendInitialValue");
communicateSendInitialValue();
} finally {
this.connectNTAsInstead = false;
}
}
@Tag("mqtt")
// @RepeatedIfExceptionsTest(repeats = TEST_REPETITIONS)
@Test
public void testCommunicateOnlyUpdatedValueWithNTAs() throws IOException, InterruptedException {
this.writeCurrentValue = false;
this.connectNTAsInstead = true;
try {
createModel();
setupReceiverAndConnect();
logger.info("Calling communicateOnlyUpdatedValue");
communicateOnlyUpdatedValue();
} finally {
this.connectNTAsInstead = false;
}
}
@Override @Override
protected void communicateSendInitialValue() throws IOException, InterruptedException { protected void communicateSendInitialValue() throws IOException, InterruptedException {
checker.addToNumberOfValues(4) checker.addToNumberOfValues(4)
.put(CHECK_MANY_A, tuple("am0", "am1")) .put(CHECK_MANY_A, tuple("am0", "am1"))
.put(CHECK_WITH_SUFFIX, tuple("am0post", "am1post")); .put(CHECK_WITH_SUFFIX, tuple("am0post", "am1post"));
listA0.setValue("changedValue"); communicateBoth("am1", "am0post");
checker.incNumberOfValues().put(CHECK_MANY_A, tuple("changedValue", "am1")).check();
// setting same value must not change data, and must not trigger a new sent message
listA0.setValue("changedValue");
checker.check();
listA1.setValue("");
checker.incNumberOfValues().put(CHECK_MANY_A, tuple("changedValue", "")).check();
listA1InSuffix.setValue("re");
checker.incNumberOfValues().put(CHECK_WITH_SUFFIX, tuple("am0post", "repost")).check();
// adding a new element does not automatically send it
A listA3InSuffix = createA("out");
senderRoot.addMultipleAWithSuffix(listA3InSuffix);
checker.check();
// only after connecting it, the element gets sent
assertTrue(senderRoot.connectMultipleAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_2), 2, true));
checker.incNumberOfValues().put(CHECK_WITH_SUFFIX, tuple("am0post", "repost", "outpost")).check();
// after successful disconnect, no messages will be sent
assertTrue(senderRoot.disconnectMultipleAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_0)));
listA0InSuffix.setValue("willBeIgnored");
checker.check();
} }
@Override @Override
...@@ -154,10 +183,10 @@ public class IndexedSendTest extends AbstractMqttTest { ...@@ -154,10 +183,10 @@ public class IndexedSendTest extends AbstractMqttTest {
checker.put(CHECK_MANY_A, tuple()) checker.put(CHECK_MANY_A, tuple())
.put(CHECK_WITH_SUFFIX, tuple()); .put(CHECK_WITH_SUFFIX, tuple());
communicateBoth(); communicateBoth(null, null);
} }
private void communicateBoth() throws IOException { private void communicateBoth(String manyAtIndex1, String suffixAtIndex0) throws IOException {
// Sink.ManyA <-- Root.MultipleA // Sink.ManyA <-- Root.MultipleA
// Sink.ManyAWithSuffix <-- Root.MultipleAWithSuffix // Sink.ManyAWithSuffix <-- Root.MultipleAWithSuffix
checker.check(); checker.check();
...@@ -165,18 +194,26 @@ public class IndexedSendTest extends AbstractMqttTest { ...@@ -165,18 +194,26 @@ public class IndexedSendTest extends AbstractMqttTest {
assertEquals(listA0.getValue(), senderRoot._ragconnect_MultipleA(0).getValue()); assertEquals(listA0.getValue(), senderRoot._ragconnect_MultipleA(0).getValue());
listA0.setValue("changedValue"); listA0.setValue("changedValue");
assertEquals(listA0.getValue(), senderRoot._ragconnect_MultipleA(0).getValue()); assertEquals(listA0.getValue(), senderRoot._ragconnect_MultipleA(0).getValue());
checker.incNumberOfValues().put(CHECK_MANY_A, tuple("changedValue")).check();
checker.incNumberOfValues()
.put(CHECK_MANY_A, manyAtIndex1 != null ? tuple("changedValue", manyAtIndex1) : tuple("changedValue"))
.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();
// first element in suffix-list // first element in suffix-list
listA1InSuffix.setValue("re"); listA1InSuffix.setValue("re");
checker.incNumberOfValues().put(CHECK_WITH_SUFFIX, tuple("repost")).check(); checker.incNumberOfValues()
.put(CHECK_WITH_SUFFIX, suffixAtIndex0 != null ? tuple(suffixAtIndex0, "repost") : tuple("repost"))
.check();
// adding a new element does not automatically send it // adding a new element does not automatically send it
A listA3InSuffix = createA("out"); A listA3InSuffix = createA("out");
...@@ -185,7 +222,9 @@ public class IndexedSendTest extends AbstractMqttTest { ...@@ -185,7 +222,9 @@ public class IndexedSendTest extends AbstractMqttTest {
// only after connecting it, the element gets sent // only after connecting it, the element gets sent
assertTrue(senderRoot.connectMultipleAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_2), 2, true)); assertTrue(senderRoot.connectMultipleAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_2), 2, true));
checker.incNumberOfValues().put(CHECK_WITH_SUFFIX, tuple("repost", "outpost")).check(); checker.incNumberOfValues()
.put(CHECK_WITH_SUFFIX, suffixAtIndex0 != null ? tuple(suffixAtIndex0, "repost", "outpost") : tuple("repost", "outpost"))
.check();
// after successful disconnect, no messages will be sent // after successful disconnect, no messages will be sent
assertTrue(senderRoot.disconnectMultipleAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_0))); assertTrue(senderRoot.disconnectMultipleAWithSuffix(mqttUri(TOPIC_A_MANY_SUFFIX_0)));
...@@ -193,6 +232,12 @@ public class IndexedSendTest extends AbstractMqttTest { ...@@ -193,6 +232,12 @@ public class IndexedSendTest extends AbstractMqttTest {
checker.check(); checker.check();
} }
private String prettyPrint(JastAddList<A> aList) {
StringJoiner sj = new StringJoiner(", ", "[", "]");
aList.forEach(a -> sj.add(a.getValue() + "(" + a.getInner().getInnerValue() + ")"));
return sj.toString();
}
@Override @Override
protected void closeConnections() { protected void closeConnections() {
if (handler != null) { if (handler != null) {
......
...@@ -22,6 +22,7 @@ import java.util.*; ...@@ -22,6 +22,7 @@ import java.util.*;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate; 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;
...@@ -226,20 +227,30 @@ public class TestUtils { ...@@ -226,20 +227,30 @@ public class TestUtils {
} }
public TestChecker setActual(String name, Callable<T> actual) { public TestChecker setActual(String name, Callable<T> actual) {
values.computeIfAbsent(name, ActualAndExpected::new).actual = actual; _computeIfAbsent(name).actual = actual;
return parent; return parent;
} }
public TestChecker setCheck(String name, BiConsumer<String, T> check) { public TestChecker setCheck(String name, BiConsumer<String, T> check) {
values.computeIfAbsent(name, ActualAndExpected::new).customCheck = check; _computeIfAbsent(name).customCheck = check;
return parent; return parent;
} }
public TestChecker put(String name, T expected) { public TestChecker put(String name, T expected) {
values.computeIfAbsent(name, ActualAndExpected::new).expected = expected; _computeIfAbsent(name).expected = expected;
return parent; return parent;
} }
public TestChecker updateExpected(String name, Function<T, T> updater) {
ActualAndExpected<T> aae = _computeIfAbsent(name);
aae.expected = updater.apply(aae.expected);
return parent;
}
private ActualAndExpected<T> _computeIfAbsent(String name) {
return values.computeIfAbsent(name, ActualAndExpected::new);
}
ActualAndExpected<T> get(String name) { ActualAndExpected<T> get(String name) {
return values.get(name); return values.get(name);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment