diff --git a/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd b/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd
index da358f6f9c591f5ef5ce6e392219ca30169a0984..7e4bde916d565d16bdef34598d638d2080f2f5fa 100644
--- a/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd
+++ b/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd
@@ -102,8 +102,8 @@ aspect AttributesForMustache {
       return preemptiveExpectedValue() + " == " + lastResult();
     }
     if (endpointDef().isReceiveTypeEndpointDefinition() && endpointDef().asReceiveTypeEndpointDefinition().getWithAdd()) {
-      // only check if received list is empty (may also be skipped, since addAll would not do anything anyways)
-      return lastResult() + " == null || " + lastResult() + ".numChildren() == 0";
+      // only check if received list is not null
+      return lastResult() + " == null";
     }
     if (endpointDef().isTypeEndpointDefinition() && type().isOptComponent()) {
       // use "hasX()" instead of "getX() != null" for optionals
diff --git a/ragconnect.tests/build.gradle b/ragconnect.tests/build.gradle
index fdea9d0ae1751e509bbcc37ef97b1b9840a327c3..61470f5292531d0ec7ca5d3691a3b248bcff1588 100644
--- a/ragconnect.tests/build.gradle
+++ b/ragconnect.tests/build.gradle
@@ -503,3 +503,62 @@ task compileSingleListIncremental(type: RagConnectTest, dependsOn: ':ragconnect.
                         '--flush=full']
     }
 }
+
+// --- Test: singleListVariant-manual ---
+task compileSingleListVariantManual(type: RagConnectTest, dependsOn: ':ragconnect.base:jar') {
+    ragconnect {
+        outputDir = file('src/test/02-after-ragconnect/singleListVariant')
+        inputFiles = [file('src/test/01-input/singleListVariant/Test.relast'),
+                      file('src/test/01-input/singleListVariant/Test.connect'),
+                      file('src/test/01-input/singleListVariant/TestDependencies.connect')]
+        rootNode = 'Root'
+    }
+    relast {
+        useJastAddNames = true
+        grammarName = 'src/test/03-after-relast/singleListVariant/singleListVariant'
+        serializer = 'jackson'
+    }
+    jastadd {
+        jastAddList = 'JastAddList'
+        packageName = 'singleListVariant.ast'
+        inputFiles = [file('src/test/01-input/singleListVariant/Test.jadd')]
+    }
+}
+
+// --- Test: singleListVariant-incremental ---
+task compileSingleListVariantIncremental(type: RagConnectTest, dependsOn: ':ragconnect.base:jar') {
+    ragconnect {
+        outputDir = file('src/test/02-after-ragconnect/singleListVariantInc')
+        inputFiles = [file('src/test/01-input/singleListVariant/Test.relast'),
+                      file('src/test/01-input/singleListVariant/Test.connect')]
+        rootNode = 'Root'
+    }
+    relast {
+        useJastAddNames = true
+        grammarName = 'src/test/03-after-relast/singleListVariantInc/singleListVariantInc'
+        serializer = 'jackson'
+    }
+    jastadd {
+        jastAddList = 'JastAddList'
+        packageName = 'singleListVariantInc.ast'
+        inputFiles = [file('src/test/01-input/singleListVariant/Test.jadd')]
+        extraOptions = ['--tracing=cache,flush',
+                        '--incremental=param',
+                        '--cache=all',
+                        '--rewrite=cnta',
+                        '--flush=full']
+    }
+}
+
+//task cleanCurrentManualTest(type: Delete) {
+//    delete "src/test/02-after-ragconnect/singleListVariant"
+//    delete "src/test/03-after-relast/singleListVariant"
+//    delete "src/test/java-gen/singleListVariant/ast"
+//}
+//task cleanCurrentIncrementalTest(type: Delete) {
+//    delete "src/test/02-after-ragconnect/singleListVariantInc"
+//    delete "src/test/03-after-relast/singleListVariantInc"
+//    delete "src/test/java-gen/singleListVariantInc/ast"
+//}
+//compileSingleListVariantManual.dependsOn cleanCurrentManualTest
+//compileSingleListVariantIncremental.dependsOn cleanCurrentIncrementalTest
diff --git a/ragconnect.tests/src/test/01-input/singleList/Test.relast b/ragconnect.tests/src/test/01-input/singleList/Test.relast
index 59e57d7f4c5d526b6831ea8fd090960f5d4c9e08..0d97bb6c6b2fa4be6a4628b5e7e45926817364d0 100644
--- a/ragconnect.tests/src/test/01-input/singleList/Test.relast
+++ b/ragconnect.tests/src/test/01-input/singleList/Test.relast
@@ -8,5 +8,4 @@ SenderRoot : Nameable ::= <Input1:int> /A1:A/
                           <InOutput:int> ;
 
 ReceiverRoot : Nameable ::= A* UsingWildcardA:A* WithAddA:A* UsingWildcardWithAddA:A* ;
-A : Nameable ::= ;
-B : Nameable ;
+A : Nameable ;
diff --git a/ragconnect.tests/src/test/01-input/singleListVariant/README.md b/ragconnect.tests/src/test/01-input/singleListVariant/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4004ac42c136c25f2447efe5c1161c98754f32c1
--- /dev/null
+++ b/ragconnect.tests/src/test/01-input/singleListVariant/README.md
@@ -0,0 +1,61 @@
+# Single List
+
+Idea: send and receive single values for lists of subtrees.
+Test different variants of the structure/shape of the send/received value.
+
+## Execution-Model
+
+TODO: check again (old model copied from `singleList`)
+
+```
+SenderRoot/ReceiverRoot
+  |- T_Empty       ::= /* empty */ ;
+  |- T_Token       ::= <Value:String> ;
+  |- T_OneChild    ::= Other ;
+  |- T_OneOpt      ::= [Other] ;
+  |- T_OneList     ::= Other* ;
+  |- T_TwoChildren ::= Left:Other Right:Other ;
+  |- T_OneOfEach   ::= First:Other [Second:Other] Third:Other* <Fourth:String> ;
+  |- abstract T_Abstract ::= <ValueAbstract> ;
+```
+
+## Computation
+
+```
+T.ID = Input
+T.token = Input
+T.Other.ID = Input + 1
+```
+
+## Execution-Trace (SendInitialValue)
+
+Inputs:
+
+- 1
+- 1
+- 2
+- 3
+
+| Input | [A1,A2,A3,A4,IO] | # | A* | UsingWcA | WithAddA | UsingWcWithAddA:A |
+|---|---|---|---|---|---|---|
+| * | [1,2,3,4,0] | 5 | [1,2,3,4,0] | [1,2,3,4,0] | [1,2,3,4,0] | [1,2,3,4,0] |
+| I1:1 | [2,2,3,4,0] | 6 | [2,2,3,4,0] | [2,2,3,4,0] | [1,2,3,4,0,2] | [1,2,3,4,0,2] |
+| I1:1 | [2,2,3,4,0] | 6 | [2,2,3,4,0] | [2,2,3,4,0] | [1,2,3,4,0,2] | [1,2,3,4,0,2] |
+| I1:2 | [3,2,3,4,0] | 7 | [3,2,3,4,0] | [3,2,3,4,0] | [1,2,3,4,0,2,3] | [1,2,3,4,0,2,3] |
+| IO:5 | [3,2,3,4,5] | 8 | [3,2,3,4,5] | [3,2,3,4,5] | [1,2,3,4,0,2,3,5] | [1,2,3,4,0,2,3,5]
+| I3:4 | [3,2,7,4,5] | 9 | [3,2,7,4,5] | [3,2,7,4,5] | [1,2,3,4,0,2,3,5,7] | [1,2,3,4,0,2,3,5,7] |
+
+*: (1:0, 2:0, 3:0, 4:0, 5:0)
+
+## Execution-Trace (OnlyUpdate)
+
+| Input | [A1,A2,A3,A4,IO] | # | A* | UsingWcA | WithAddA | UsingWcWithAddA:A |
+|---|---|---|---|---|---|---|
+| * | [-,-,-,-,-] | 0 | [0,0,0,0,0] | [] | [] | [] |
+| I1:1 | [2,-,-,-,-] | 1 | [2,0,0,0,0] | [2] | [2] | [2] |
+| I1:1 | [2,-,-,-,-] | 1 | [2,0,0,0,0] | [2] | [2] | [2] |
+| I1:2 | [3,-,-,-,-] | 2 | [3,0,0,0,0] | [3] | [2,3] | [2,3] |
+| IO:5 | [2,-,-,-,5] | 3 | [3,0,0,0,5] | [3,5] | [2,3,5] | [2,3,5]
+| I3:4 | [2,-,7,-,5] | 4 | [3,0,7,0,5] | [3,5,7] | [2,3,5,7] | [2,3,5,7] |
+
+*: (1:0, 2:0, 3:0, 4:0, 5:0)
diff --git a/ragconnect.tests/src/test/01-input/singleListVariant/Test.connect b/ragconnect.tests/src/test/01-input/singleListVariant/Test.connect
new file mode 100644
index 0000000000000000000000000000000000000000..23365109901425e8a6060c3ef3c2d8fe4cfc7656
--- /dev/null
+++ b/ragconnect.tests/src/test/01-input/singleListVariant/Test.connect
@@ -0,0 +1,28 @@
+send tree SenderRoot.T_Empty ;
+send tree SenderRoot.T_Token ;
+send tree SenderRoot.T_OneChild ;
+send tree SenderRoot.T_OneOpt ;
+send tree SenderRoot.T_OneList ;
+send tree SenderRoot.T_TwoChildren ;
+send tree SenderRoot.T_OneOfEach ;
+send tree SenderRoot.T_Abstract ;
+
+receive tree ReceiverRoot.T_Empty ;
+receive tree ReceiverRoot.T_Token ;
+receive tree ReceiverRoot.T_OneChild ;
+receive tree ReceiverRoot.T_OneOpt ;
+receive tree ReceiverRoot.T_OneList ;
+receive tree ReceiverRoot.T_TwoChildren ;
+receive tree ReceiverRoot.T_OneOfEach ;
+receive tree ReceiverRoot.T_Abstract ;
+
+receive tree ReceiverRoot.MyEmpty ;
+
+receive tree with add ReceiverRoot.EmptyWithAdd ;
+receive tree with add ReceiverRoot.TokenWithAdd ;
+receive tree with add ReceiverRoot.OneChildWithAdd ;
+receive tree with add ReceiverRoot.OneOptWithAdd ;
+receive tree with add ReceiverRoot.OneListWithAdd ;
+receive tree with add ReceiverRoot.TwoChildrenWithAdd ;
+receive tree with add ReceiverRoot.OneOfEachWithAdd ;
+receive tree with add ReceiverRoot.AbstractWithAdd ;
diff --git a/ragconnect.tests/src/test/01-input/singleListVariant/Test.jadd b/ragconnect.tests/src/test/01-input/singleListVariant/Test.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..10ed1174a4cbb99e46cd5ba582df829d547bd446
--- /dev/null
+++ b/ragconnect.tests/src/test/01-input/singleListVariant/Test.jadd
@@ -0,0 +1,75 @@
+aspect Computation {
+  syn T_Empty SenderRoot.getT_Empty() = new T_Empty().setID(getInput());
+  syn T_Token SenderRoot.getT_Token() = new T_Token().setID(getInput())
+    .setValue(Integer.toString(getInput()));
+  syn T_OneChild SenderRoot.getT_OneChild() {
+    T_OneChild result = new T_OneChild().setID(getInput());
+    result.setOther(createOther());
+    return result;
+  }
+  syn T_OneOpt SenderRoot.getT_OneOpt() {
+    T_OneOpt result = new T_OneOpt().setID(getInput());
+    if (getShouldSetOptAndList()) {
+      result.setOther(createOther());
+    }
+    return result;
+  }
+  syn T_OneList SenderRoot.getT_OneList() {
+    T_OneList result = new T_OneList().setID(getInput());
+    if (getShouldSetOptAndList()) {
+      result.addOther(createOther());
+    }
+    return result;
+  }
+  syn T_TwoChildren SenderRoot.getT_TwoChildren() {
+    T_TwoChildren result = new T_TwoChildren().setID(getInput());
+    result.setLeft(createOther());
+    result.setRight(createOther());
+    return result;
+  }
+  syn T_OneOfEach SenderRoot.getT_OneOfEach() {
+    T_OneOfEach result = new T_OneOfEach().setID(getInput());
+    result.setFirst(createOther());
+    if (getShouldSetOptAndList()) {
+      result.setSecond(createOther());
+      result.addThird(createOther());
+    }
+    result.setFourth(Integer.toString(getInput()));
+    return result;
+  }
+  syn T_Abstract SenderRoot.getT_Abstract() = new T_SubClass()
+    .setValueSub(Integer.toString(getInput()))
+    .setID(getInput())
+    .setValueAbstract(Integer.toString(getInput()));
+
+  private Other SenderRoot.createOther() {
+    return new Other().setID(getInput() + 1);
+  }
+
+  syn boolean ASTNode.isNameable() = false;
+  eq Nameable.isNameable() = true;
+}
+
+aspect Testing {
+  class SenderRoot implements org.jastadd.ragconnect.tests.singleListVariant.AbstractSingleListVariantTest.TestWrapperSenderRoot {}
+  class ReceiverRoot implements org.jastadd.ragconnect.tests.singleListVariant.AbstractSingleListVariantTest.TestWrapperReceiverRoot {}
+  class Other implements org.jastadd.ragconnect.tests.singleListVariant.AbstractSingleListVariantTest.TestWrapperOther {}
+  class T_Empty  implements org.jastadd.ragconnect.tests.singleListVariant.AbstractSingleListVariantTest.TestWrapperT_Empty {}
+  class T_Token  implements org.jastadd.ragconnect.tests.singleListVariant.AbstractSingleListVariantTest.TestWrapperT_Token {}
+  class T_OneChild  implements org.jastadd.ragconnect.tests.singleListVariant.AbstractSingleListVariantTest.TestWrapperT_OneChild {}
+  class T_OneOpt  implements org.jastadd.ragconnect.tests.singleListVariant.AbstractSingleListVariantTest.TestWrapperT_OneOpt {}
+  class T_OneList  implements org.jastadd.ragconnect.tests.singleListVariant.AbstractSingleListVariantTest.TestWrapperT_OneList {}
+  class T_TwoChildren  implements org.jastadd.ragconnect.tests.singleListVariant.AbstractSingleListVariantTest.TestWrapperT_TwoChildren {}
+  class T_OneOfEach  implements org.jastadd.ragconnect.tests.singleListVariant.AbstractSingleListVariantTest.TestWrapperT_OneOfEach {}
+  class T_Abstract  implements org.jastadd.ragconnect.tests.singleListVariant.AbstractSingleListVariantTest.TestWrapperT_Abstract {}
+  class JastAddList<T> implements org.jastadd.ragconnect.tests.singleListVariant.AbstractSingleListVariantTest.TestWrapperJastAddList<T> {}
+}
+
+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 Nameable.customID() {
+    return getClass().getSimpleName() + getID();
+  }
+}
diff --git a/ragconnect.tests/src/test/01-input/singleListVariant/Test.relast b/ragconnect.tests/src/test/01-input/singleListVariant/Test.relast
new file mode 100644
index 0000000000000000000000000000000000000000..4ac99ae124e19d182d9ad23b4c4ae65980272013
--- /dev/null
+++ b/ragconnect.tests/src/test/01-input/singleListVariant/Test.relast
@@ -0,0 +1,44 @@
+Root ::= SenderRoot* ReceiverRoot* ;
+
+Nameable ::= <ID:int> ;
+SenderRoot : Nameable ::= <Input:int> <ShouldSetOptAndList:boolean>
+/T_Empty/
+/T_Token/
+/T_OneChild/
+/T_OneOpt/
+/T_OneList/
+/T_TwoChildren/
+/T_OneOfEach/
+/T_Abstract/
+;
+
+ReceiverRoot : Nameable ::=
+T_Empty*
+T_Token*
+T_OneChild*
+T_OneOpt*
+T_OneList*
+T_TwoChildren*
+T_OneOfEach*
+T_Abstract*
+MyEmpty:T_Empty*
+EmptyWithAdd:T_Empty*
+TokenWithAdd:T_Token*
+OneChildWithAdd:T_OneChild*
+OneOptWithAdd:T_OneOpt*
+OneListWithAdd:T_OneList*
+TwoChildrenWithAdd:T_TwoChildren*
+OneOfEachWithAdd:T_OneOfEach*
+AbstractWithAdd:T_Abstract*
+;
+
+T_Empty : Nameable       ::= /* empty */ ;
+T_Token : Nameable       ::= <Value:String> ;
+T_OneChild : Nameable    ::= Other ;
+T_OneOpt : Nameable      ::= [Other] ;
+T_OneList : Nameable     ::= Other* ;
+T_TwoChildren : Nameable ::= Left:Other Right:Other ;
+T_OneOfEach : Nameable   ::= First:Other [Second:Other] Third:Other* <Fourth:String> ;
+abstract T_Abstract : Nameable ::= <ValueAbstract>;
+T_SubClass : T_Abstract  ::= <ValueSub> ;
+Other : Nameable ;
diff --git a/ragconnect.tests/src/test/01-input/singleListVariant/TestDependencies.connect b/ragconnect.tests/src/test/01-input/singleListVariant/TestDependencies.connect
new file mode 100644
index 0000000000000000000000000000000000000000..2ac87895268cfa631fcfee65a8c2c90f4c13b3c7
--- /dev/null
+++ b/ragconnect.tests/src/test/01-input/singleListVariant/TestDependencies.connect
@@ -0,0 +1,16 @@
+SenderRoot.T_Empty canDependOn SenderRoot.Input as InputDependencyToT_Empty ;
+SenderRoot.T_Token canDependOn SenderRoot.Input as InputDependencyToT_Token ;
+SenderRoot.T_OneChild canDependOn SenderRoot.Input as InputDependencyToT_OneChild ;
+
+SenderRoot.T_OneOpt canDependOn SenderRoot.ShouldSetOptAndList as ShouldSetOptAndListDependencyToT_OneOpt ;
+SenderRoot.T_OneOpt canDependOn SenderRoot.Input as InputDependencyToT_OneOpt ;
+
+SenderRoot.T_OneList canDependOn SenderRoot.ShouldSetOptAndList as ShouldSetOptAndListDependencyToT_OneList ;
+SenderRoot.T_OneList canDependOn SenderRoot.Input as InputDependencyToT_OneList ;
+
+SenderRoot.T_TwoChildren canDependOn SenderRoot.Input as InputDependencyToT_TwoChildren ;
+
+SenderRoot.T_OneOfEach canDependOn SenderRoot.ShouldSetOptAndList as ShouldSetOptAndListDependencyToT_OneOfEach ;
+SenderRoot.T_OneOfEach canDependOn SenderRoot.Input as InputDependencyToT_OneOfEach ;
+
+SenderRoot.T_Abstract canDependOn SenderRoot.Input as InputDependencyToT_Abstract ;
diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/singleListVariant/AbstractSingleListVariantTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/singleListVariant/AbstractSingleListVariantTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..465ad8ac024d595f29a87757c776db6c88e72fe4
--- /dev/null
+++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/singleListVariant/AbstractSingleListVariantTest.java
@@ -0,0 +1,406 @@
+package org.jastadd.ragconnect.tests.singleListVariant;
+
+import org.jastadd.ragconnect.tests.AbstractMqttTest;
+import org.jastadd.ragconnect.tests.TestUtils;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.function.BiConsumer;
+
+import static java.lang.Math.abs;
+import static java.util.Collections.addAll;
+import static org.assertj.core.util.Lists.newArrayList;
+import static org.jastadd.ragconnect.tests.TestUtils.mqttUri;
+import static org.jastadd.ragconnect.tests.TestUtils.testJaddContainReferenceToJackson;
+import static org.jastadd.ragconnect.tests.singleListVariant.AbstractSingleListVariantTest.IntList.list;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Base class for test cases "singleList manual" and "singleList incremental".
+ *
+ * @author rschoene - Initial contribution
+ */
+@Tag("List")
+@Tag("SingleList")
+public abstract class AbstractSingleListVariantTest extends AbstractMqttTest {
+
+  public interface TestWrapperJastAddList<T> extends Iterable<T> {
+    int getNumChild();
+  }
+  public interface TestWrapperReceiverRoot {
+    TestWrapperJastAddList<? extends TestWrapperT_Empty> getT_EmptyList();
+    TestWrapperJastAddList<? extends TestWrapperT_Token> getT_TokenList();
+    TestWrapperJastAddList<? extends TestWrapperT_OneChild> getT_OneChildList();
+    TestWrapperJastAddList<? extends TestWrapperT_OneOpt> getT_OneOptList();
+    TestWrapperJastAddList<? extends TestWrapperT_OneList> getT_OneListList();
+    TestWrapperJastAddList<? extends TestWrapperT_TwoChildren> getT_TwoChildrenList();
+    TestWrapperJastAddList<? extends TestWrapperT_OneOfEach> getT_OneOfEachList();
+    TestWrapperJastAddList<? extends TestWrapperT_Abstract> getT_AbstractList();
+
+    TestWrapperJastAddList<? extends TestWrapperT_Empty> getMyEmptyList();
+
+    TestWrapperJastAddList<? extends TestWrapperT_Empty> getEmptyWithAddList();
+    TestWrapperJastAddList<? extends TestWrapperT_Token> getTokenWithAddList();
+    TestWrapperJastAddList<? extends TestWrapperT_OneChild> getOneChildWithAddList();
+    TestWrapperJastAddList<? extends TestWrapperT_OneOpt> getOneOptWithAddList();
+    TestWrapperJastAddList<? extends TestWrapperT_OneList> getOneListWithAddList();
+    TestWrapperJastAddList<? extends TestWrapperT_TwoChildren> getTwoChildrenWithAddList();
+    TestWrapperJastAddList<? extends TestWrapperT_OneOfEach> getOneOfEachWithAddList();
+    TestWrapperJastAddList<? extends TestWrapperT_Abstract> getAbstractWithAddList();
+
+    boolean connectT_Empty(String mqttUri) throws IOException;
+    boolean connectT_Token(String mqttUri) throws IOException;
+    boolean connectT_OneChild(String mqttUri) throws IOException;
+    boolean connectT_OneOpt(String mqttUri) throws IOException;
+    boolean connectT_OneList(String mqttUri) throws IOException;
+    boolean connectT_TwoChildren(String mqttUri) throws IOException;
+    boolean connectT_OneOfEach(String mqttUri) throws IOException;
+    boolean connectT_Abstract(String mqttUri) throws IOException;
+
+    boolean connectMyEmpty(String mqttUri) throws IOException;
+
+    boolean connectEmptyWithAdd(String mqttUri) throws IOException;
+    boolean connectTokenWithAdd(String mqttUri) throws IOException;
+    boolean connectOneChildWithAdd(String mqttUri) throws IOException;
+    boolean connectOneOptWithAdd(String mqttUri) throws IOException;
+    boolean connectOneListWithAdd(String mqttUri) throws IOException;
+    boolean connectTwoChildrenWithAdd(String mqttUri) throws IOException;
+    boolean connectOneOfEachWithAdd(String mqttUri) throws IOException;
+    boolean connectAbstractWithAdd(String mqttUri) throws IOException;
+  }
+  @SuppressWarnings("UnusedReturnValue")
+  public interface TestWrapperSenderRoot {
+    boolean connectT_Empty(String mqttUri, boolean writeCurrentValue) throws IOException;
+    boolean connectT_Token(String mqttUri, boolean writeCurrentValue) throws IOException;
+    boolean connectT_OneChild(String mqttUri, boolean writeCurrentValue) throws IOException;
+    boolean connectT_OneOpt(String mqttUri, boolean writeCurrentValue) throws IOException;
+    boolean connectT_OneList(String mqttUri, boolean writeCurrentValue) throws IOException;
+    boolean connectT_TwoChildren(String mqttUri, boolean writeCurrentValue) throws IOException;
+    boolean connectT_OneOfEach(String mqttUri, boolean writeCurrentValue) throws IOException;
+    boolean connectT_Abstract(String mqttUri, boolean writeCurrentValue) throws IOException;
+
+    TestWrapperSenderRoot setInput(int input);
+    TestWrapperSenderRoot setShouldSetOptAndList(boolean shouldSetOptAndList);
+    TestWrapperT_Empty getT_Empty();
+    TestWrapperT_OneOpt getT_OneOpt();
+  }
+  public interface TestWrapperNameable {
+    int getID();
+  }
+  public interface TestWrapperOther extends TestWrapperNameable {}
+  public interface TestWrapperT_Empty extends TestWrapperNameable {}
+  public interface TestWrapperT_Token extends TestWrapperNameable {
+    String getValue();
+  }
+  public interface TestWrapperT_OneChild extends TestWrapperNameable {
+    TestWrapperNameable getOther();
+  }
+  public interface TestWrapperT_OneOpt extends TestWrapperNameable {
+    boolean hasOther();
+    TestWrapperNameable getOther();
+  }
+  public interface TestWrapperT_OneList extends TestWrapperNameable {
+    int getNumOther();
+    TestWrapperNameable getOther(int index);
+  }
+  public interface TestWrapperT_TwoChildren extends TestWrapperNameable {
+    TestWrapperNameable getLeft();
+    TestWrapperNameable getRight();
+  }
+  public interface TestWrapperT_OneOfEach extends TestWrapperNameable {
+    TestWrapperNameable getFirst();
+    boolean hasSecond();
+    TestWrapperNameable getSecond();
+    int getNumThird();
+    TestWrapperNameable getThird(int index);
+    String getFourth();
+  }
+  public interface TestWrapperT_Abstract extends TestWrapperNameable {
+    String getValueAbstract();
+    String getValueSub();
+  }
+
+  AbstractSingleListVariantTest(String shortName) {
+    this.shortName = shortName;
+  }
+
+  protected static final String TOPIC_T_Empty = "t/Empty";
+  protected static final String TOPIC_T_Token = "t/Token";
+  protected static final String TOPIC_T_OneChild = "t/OneChild";
+  protected static final String TOPIC_T_OneOpt = "t/OneOpt";
+  protected static final String TOPIC_T_OneList = "t/OneList";
+  protected static final String TOPIC_T_TwoChildren = "t/TwoChildren";
+  protected static final String TOPIC_T_OneOfEach = "t/OneOfEach";
+  protected static final String TOPIC_T_Abstract = "t/Abstract";
+  protected static final String TOPIC_T_all = "t/#";
+
+  protected TestWrapperSenderRoot senderRoot;
+  protected TestWrapperReceiverRoot receiverRoot;
+  protected ReceiverData data;
+
+  private final String shortName;
+
+  @Test
+  public void checkJacksonReference() {
+    testJaddContainReferenceToJackson(
+        Paths.get("src", "test",
+            "02-after-ragconnect", shortName, "RagConnect.jadd"), true);
+  }
+
+  @Override
+  protected void setupReceiverAndConnect(boolean writeCurrentValue) throws IOException, InterruptedException {
+    // late model initialization
+    setInput(0);
+    setShouldSetOptAndList(false);
+
+    setupReceiverAndConnectPart();
+
+    // connect. important: first receivers, then senders. to not miss initial value.
+
+    // receive: unnamed
+    assertTrue(receiverRoot.connectT_Empty(mqttUri(TOPIC_T_Empty)));
+    assertTrue(receiverRoot.connectT_Token(mqttUri(TOPIC_T_Token)));
+    assertTrue(receiverRoot.connectT_OneChild(mqttUri(TOPIC_T_OneChild)));
+    assertTrue(receiverRoot.connectT_OneOpt(mqttUri(TOPIC_T_OneOpt)));
+    assertTrue(receiverRoot.connectT_OneList(mqttUri(TOPIC_T_OneList)));
+    assertTrue(receiverRoot.connectT_TwoChildren(mqttUri(TOPIC_T_TwoChildren)));
+    assertTrue(receiverRoot.connectT_OneOfEach(mqttUri(TOPIC_T_OneOfEach)));
+    assertTrue(receiverRoot.connectT_Abstract(mqttUri(TOPIC_T_Abstract)));
+
+    // receive: named
+    assertTrue(receiverRoot.connectMyEmpty(mqttUri(TOPIC_T_Empty)));
+
+    // receive: with add
+    assertTrue(receiverRoot.connectEmptyWithAdd(mqttUri(TOPIC_T_Empty)));
+    assertTrue(receiverRoot.connectTokenWithAdd(mqttUri(TOPIC_T_Token)));
+    assertTrue(receiverRoot.connectOneChildWithAdd(mqttUri(TOPIC_T_OneChild)));
+    assertTrue(receiverRoot.connectOneOptWithAdd(mqttUri(TOPIC_T_OneOpt)));
+    assertTrue(receiverRoot.connectOneListWithAdd(mqttUri(TOPIC_T_OneList)));
+    assertTrue(receiverRoot.connectTwoChildrenWithAdd(mqttUri(TOPIC_T_TwoChildren)));
+    assertTrue(receiverRoot.connectOneOfEachWithAdd(mqttUri(TOPIC_T_OneOfEach)));
+    assertTrue(receiverRoot.connectAbstractWithAdd(mqttUri(TOPIC_T_Abstract)));
+
+    // send
+    assertTrue(senderRoot.connectT_Empty(mqttUri(TOPIC_T_Empty), writeCurrentValue));
+    assertTrue(senderRoot.connectT_Token(mqttUri(TOPIC_T_Token), writeCurrentValue));
+    assertTrue(senderRoot.connectT_OneChild(mqttUri(TOPIC_T_OneChild), writeCurrentValue));
+    assertTrue(senderRoot.connectT_OneOpt(mqttUri(TOPIC_T_OneOpt), writeCurrentValue));
+    assertTrue(senderRoot.connectT_OneList(mqttUri(TOPIC_T_OneList), writeCurrentValue));
+    assertTrue(senderRoot.connectT_TwoChildren(mqttUri(TOPIC_T_TwoChildren), writeCurrentValue));
+    assertTrue(senderRoot.connectT_OneOfEach(mqttUri(TOPIC_T_OneOfEach), writeCurrentValue));
+    assertTrue(senderRoot.connectT_Abstract(mqttUri(TOPIC_T_Abstract), writeCurrentValue));
+  }
+
+  abstract protected void setupReceiverAndConnectPart() throws IOException;
+
+  @Override
+  protected void communicateSendInitialValue() throws InterruptedException {
+    // transmissions: 8 * 1 = 8
+    checkTree(8, list(-0), list(0), list(-0));
+
+    setInput(1);
+    // transmissions: 8 + 8 = 16
+    checkTree(16, list(-1), list(0, 1), list(-0, -1));
+
+    setInput(1);
+    // transmissions: 16
+    checkTree(16, list(-1), list(0, 1), list(-0, -1));
+
+    setShouldSetOptAndList(true);
+    // transmissions: 16 + 3 = 19
+    checkTree(19, list(1), list(0, 1), list(-0, -1, 1));
+
+    setShouldSetOptAndList(true);
+    // transmissions: 19
+    checkTree(19, list(1), list(0, 1), list(-0, -1, 1));
+
+    setInput(2);
+    // transmissions: 19 + 8 = 27
+    checkTree(27, list(2), list(0, 1, 2), list(-0, -1, 1, 2));
+
+    setInput(5);
+    // transmissions: 27 + 8 = 35
+    checkTree(35, list(5), list(0, 1, 2, 5), list(-0, -1, 1, 2, 5));
+  }
+
+  @Override
+  protected void communicateOnlyUpdatedValue() throws InterruptedException {
+    // transmissions: 0
+    checkTree(0, list(), list(), list());
+
+    setInput(1);
+    // transmissions: 8 * 1 = 0
+    checkTree(8, list(-1), list(1), list(-1));
+
+    setInput(1);
+    // transmissions: 8
+    checkTree(8, list(-1), list(1), list(-1));
+
+    setShouldSetOptAndList(true);
+    // transmissions: 8 + 3 = 11
+    checkTree(11, list(1), list(1), list(-1, 1));
+
+    setShouldSetOptAndList(true);
+    // transmissions: 11
+    checkTree(11, list(1), list(1), list(-1, 1));
+
+    setInput(2);
+    // transmissions: 11 + 8 = 19
+    checkTree(19, list(2), list(1, 2), list(-1, 1, 2));
+
+    setInput(5);
+    // transmissions: 19 + 8 = 27
+    checkTree(27, list(5), list(1, 2, 5), list(-1, 1, 2, 5));
+  }
+
+  protected void setInput(int input) {
+    senderRoot.setInput(input);
+    assertEquals(input, senderRoot.getT_Empty().getID(), "ID value of empty");
+  }
+
+  protected void setShouldSetOptAndList(boolean shouldSetOptAndList) {
+    senderRoot.setShouldSetOptAndList(shouldSetOptAndList);
+    assertEquals(shouldSetOptAndList, senderRoot.getT_OneOpt().hasOther(), "opt is filled or not");
+  }
+
+  /**
+   * Check against expected lists of IDs.
+   * If an ID is negative, do not check Opts and Lists, but use absolute value for comparison.
+   * The tests starts with ID 0 and does not use opts and lists at this point, so checking with > 0 is used.
+   * @param expectedTransmissions            expected number of total transmissions
+   * @param expectedList                     ids for unnamed and named endpoints without add
+   * @param expectedWithAddList              ids for endpoints with add, but not those with opts and lists
+   *                                         (only positive numbers can/need to be passed)
+   * @param expectedWithAddListForOptAndList ids for endpoints with add and with opts and lists
+   * @throws InterruptedException if interrupted in TestUtils.waitForMqtt
+   */
+  private void checkTree(int expectedTransmissions,
+                         IntList expectedList,
+                         IntList expectedWithAddList,
+                         IntList expectedWithAddListForOptAndList)
+      throws InterruptedException {
+    TestUtils.waitForMqtt();
+    assertEquals(expectedTransmissions, data.numberOfElements, "transmissions for any element");
+
+    // check unnamed
+    checkList(expectedList.toList(), receiverRoot.getT_EmptyList(), (e, n) -> {});
+    checkList(expectedList.toList(), receiverRoot.getT_TokenList(),
+        (e, n) -> assertEquals(Integer.toString(abs(e)), n.getValue()));
+    checkList(expectedList.toList(), receiverRoot.getT_OneChildList(),
+        (e, n) -> assertEquals(abs(e) + 1, n.getOther().getID()));
+    checkList(expectedList.toList(), receiverRoot.getT_OneOptList(),
+        (e, n) -> {
+          assertEquals(e > 0, n.hasOther());
+          if (n.hasOther()) {
+            assertEquals(abs(e) + 1, n.getOther().getID());
+          }
+        });
+    checkList(expectedList.toList(), receiverRoot.getT_OneListList(),
+        (e, n) -> {
+          assertEquals(e > 0 ? 1 : 0, n.getNumOther());
+          if (n.getNumOther() > 0) {
+            assertEquals(abs(e) + 1, n.getOther(0).getID());
+          }
+        });
+    checkList(expectedList.toList(), receiverRoot.getT_TwoChildrenList(),
+        (e, n) -> {
+          assertEquals(abs(e) + 1, n.getLeft().getID());
+          assertEquals(abs(e) + 1, n.getRight().getID());
+        });
+    checkList(expectedList.toList(), receiverRoot.getT_OneOfEachList(),
+        (e, n) -> {
+          assertEquals(abs(e) + 1, n.getFirst().getID());
+          assertEquals(e > 0, n.hasSecond());
+          if (n.hasSecond()) {
+            assertEquals(abs(e) + 1, n.getSecond().getID());
+          }
+          assertEquals(e > 0 ? 1 : 0, n.getNumThird());
+          if (n.getNumThird() > 0) {
+            assertEquals(abs(e) + 1, n.getThird(0).getID());
+          }
+          assertEquals(Integer.toString(abs(e)), n.getFourth());
+        });
+    checkList(expectedList.toList(), receiverRoot.getT_AbstractList(),
+        (e, n) -> {
+          assertEquals(Integer.toString(abs(e)), n.getValueAbstract());
+          assertEquals(Integer.toString(abs(e)), n.getValueSub());
+        });
+
+    // check named
+    checkList(expectedList.toList(), receiverRoot.getMyEmptyList(), (e, n) -> {});
+
+    // check with add
+    checkList(expectedWithAddList.toList(), receiverRoot.getEmptyWithAddList(), (e, n) -> {});
+    checkList(expectedWithAddList.toList(), receiverRoot.getTokenWithAddList(),
+        (e, n) -> assertEquals(Integer.toString(abs(e)), n.getValue()));
+    checkList(expectedWithAddList.toList(), receiverRoot.getOneChildWithAddList(),
+        (e, n) -> assertEquals(abs(e) + 1, n.getOther().getID()));
+    checkList(expectedWithAddListForOptAndList.toList(), receiverRoot.getOneOptWithAddList(),
+        (e, n) -> {
+          if (n.hasOther()) {
+            assertEquals(abs(e) + 1, n.getOther().getID());
+          }
+        });
+    checkList(expectedWithAddListForOptAndList.toList(), receiverRoot.getOneListWithAddList(),
+        (e, n) -> {
+          if (n.getNumOther() > 0) {
+            assertEquals(abs(e) + 1, n.getOther(0).getID());
+          }
+        });
+    checkList(expectedWithAddList.toList(), receiverRoot.getTwoChildrenWithAddList(),
+        (e, n) -> {
+          assertEquals(abs(e) + 1, n.getLeft().getID());
+          assertEquals(abs(e) + 1, n.getRight().getID());
+        });
+    checkList(expectedWithAddListForOptAndList.toList(), receiverRoot.getOneOfEachWithAddList(),
+        (e, n) -> {
+          assertEquals(abs(e) + 1, n.getFirst().getID());
+          if (n.hasSecond()) {
+            assertEquals(abs(e) + 1, n.getSecond().getID());
+          }
+          if (n.getNumThird() > 0) {
+            assertEquals(abs(e) + 1, n.getThird(0).getID());
+          }
+          assertEquals(Integer.toString(abs(e)), n.getFourth());
+        });
+    checkList(expectedWithAddList.toList(), receiverRoot.getAbstractWithAddList(),
+        (e, n) -> {
+          assertEquals(Integer.toString(abs(e)), n.getValueAbstract());
+          assertEquals(Integer.toString(abs(e)), n.getValueSub());
+        });
+  }
+
+  private <T extends TestWrapperNameable> void checkList(List<Integer> expectedList, TestWrapperJastAddList<T> actualList, BiConsumer<Integer, T> additionalTest) {
+    assertEquals(expectedList.size(), actualList.getNumChild(), "same list size");
+    int index = 0;
+    for (T element : actualList) {
+      assertEquals(abs(expectedList.get(index)), element.getID(), "correct ID for A");
+      additionalTest.accept(expectedList.get(index), element);
+      index++;
+    }
+  }
+
+  protected static class ReceiverData {
+    int numberOfElements = 0;
+  }
+
+  protected static class IntList {
+    private final List<Integer> integers = newArrayList();
+    public IntList(Integer... values) {
+      addAll(integers, values);
+    }
+
+    public List<Integer> toList() {
+      return integers;
+    }
+
+    public static IntList list(Integer... values) {
+      return new IntList(values);
+    }
+  }
+
+}
diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/singleListVariant/SingleListVariantIncrementalVariantTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/singleListVariant/SingleListVariantIncrementalVariantTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a55da378b93cc3bcc741d1904dc58b3d9ae96bd
--- /dev/null
+++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/singleListVariant/SingleListVariantIncrementalVariantTest.java
@@ -0,0 +1,62 @@
+package org.jastadd.ragconnect.tests.singleListVariant;
+
+import org.jastadd.ragconnect.tests.TestUtils;
+import org.junit.jupiter.api.Tag;
+import singleListVariantInc.ast.*;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Test case "list incremental".
+ *
+ * @author rschoene - Initial contribution
+ */
+@Tag("Incremental")
+public class SingleListVariantIncrementalVariantTest extends AbstractSingleListVariantTest {
+
+  private Root model;
+  private MqttHandler handler;
+
+  SingleListVariantIncrementalVariantTest() {
+    super("singleListVariantInc");
+  }
+
+  @Override
+  protected void createModel() {
+    model = new Root();
+    senderRoot = new SenderRoot();
+    model.addSenderRoot((SenderRoot) senderRoot);
+
+    ReceiverRoot localReceiverRoot = new ReceiverRoot();
+    model.addReceiverRoot(localReceiverRoot);
+    receiverRoot = localReceiverRoot;
+    assertEquals(0, receiverRoot.getT_EmptyList().getNumChild());
+  }
+
+  @Override
+  protected void setupReceiverAndConnectPart() throws IOException {
+    model.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS);
+
+    handler = new MqttHandler().dontSendWelcomeMessage().setHost(TestUtils.getMqttHost());
+    assertTrue(handler.waitUntilReady(2, TimeUnit.SECONDS));
+
+    // no dependencies
+
+    data = new ReceiverData();
+    handler.newConnection(TOPIC_T_all, bytes -> data.numberOfElements += 1);
+  }
+
+  @Override
+  protected void closeConnections() {
+    if (handler != null) {
+      handler.close();
+    }
+    if (model != null) {
+      model.ragconnectCloseConnections();
+    }
+  }
+}
diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/singleListVariant/SingleListVariantManualVariantTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/singleListVariant/SingleListVariantManualVariantTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c65a09ec65add4afd7fa5ca8a2809b28e0be4df2
--- /dev/null
+++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/singleListVariant/SingleListVariantManualVariantTest.java
@@ -0,0 +1,72 @@
+package org.jastadd.ragconnect.tests.singleListVariant;
+
+import org.jastadd.ragconnect.tests.TestUtils;
+import singleListVariant.ast.*;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Test case "list manual".
+ *
+ * @author rschoene - Initial contribution
+ */
+public class SingleListVariantManualVariantTest extends AbstractSingleListVariantTest {
+
+  private Root model;
+  private MqttHandler handler;
+
+  SingleListVariantManualVariantTest() {
+    super("singleListVariant");
+  }
+
+  @Override
+  protected void createModel() {
+    model = new Root();
+    senderRoot = new SenderRoot();
+    model.addSenderRoot((SenderRoot) senderRoot);
+
+    ReceiverRoot localReceiverRoot = new ReceiverRoot();
+    model.addReceiverRoot(localReceiverRoot);
+    receiverRoot = localReceiverRoot;
+    assertEquals(0, receiverRoot.getT_EmptyList().getNumChild());
+  }
+
+  @Override
+  protected void setupReceiverAndConnectPart() throws IOException {
+    model.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS);
+
+    handler = new MqttHandler().dontSendWelcomeMessage().setHost(TestUtils.getMqttHost());
+    assertTrue(handler.waitUntilReady(2, TimeUnit.SECONDS));
+
+    // add dependencies: input
+    ((SenderRoot) senderRoot).addInputDependencyToT_Empty((SenderRoot) senderRoot);
+    ((SenderRoot) senderRoot).addInputDependencyToT_Token((SenderRoot) senderRoot);
+    ((SenderRoot) senderRoot).addInputDependencyToT_OneChild((SenderRoot) senderRoot);
+    ((SenderRoot) senderRoot).addInputDependencyToT_OneOpt((SenderRoot) senderRoot);
+    ((SenderRoot) senderRoot).addInputDependencyToT_OneList((SenderRoot) senderRoot);
+    ((SenderRoot) senderRoot).addInputDependencyToT_TwoChildren((SenderRoot) senderRoot);
+    ((SenderRoot) senderRoot).addInputDependencyToT_OneOfEach((SenderRoot) senderRoot);
+    ((SenderRoot) senderRoot).addInputDependencyToT_Abstract((SenderRoot) senderRoot);
+    // add dependencies: shouldSetOptAndList
+    ((SenderRoot) senderRoot).addShouldSetOptAndListDependencyToT_OneOpt((SenderRoot) senderRoot);
+    ((SenderRoot) senderRoot).addShouldSetOptAndListDependencyToT_OneList((SenderRoot) senderRoot);
+    ((SenderRoot) senderRoot).addShouldSetOptAndListDependencyToT_OneOfEach((SenderRoot) senderRoot);
+
+    data = new ReceiverData();
+    handler.newConnection(TOPIC_T_all, bytes -> data.numberOfElements += 1);
+  }
+
+  @Override
+  protected void closeConnections() {
+    if (handler != null) {
+      handler.close();
+    }
+    if (model != null) {
+      model.ragconnectCloseConnections();
+    }
+  }
+}