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

WIP dumpAst 0.3.1

- make excluding children work
- begin with attributes and NTAs
parent 5faedb0c
No related branches found
No related tags found
No related merge requests found
Pipeline #7867 passed
DumpAst ::= DumpNode* <PackageName> BuildConfig PrintConfig ;
BuildConfig ::= <TypeIgnore> <TokenIgnore> <ChildIgnore> <AttributeIgnore> <RelationIgnore> <IncludeEmptyString:boolean> <Debug:boolean> ;
BuildConfig ::= <TypeIgnore> <TokenIgnore> <ChildIgnore> <AttributeInclude> <NonterminalAttributeInclude> <RelationIgnore> <IncludeEmptyString:boolean> <Debug:boolean> ;
PrintConfig ::= <Scale:double> <Version> Header* ;
Header ::= <Value> ;
DumpNode ::= <Name> <Label> <Object:Object> <Invisible:boolean> DumpChildNode* DumpToken* DumpRelation* /InvisiblePath/ ;
......
......@@ -60,7 +60,7 @@ import java.lang.String;aspect GenerationFrontend {
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder disableTypes(String... regexes) {
updateIgnored(() -> buildConfig.getTypeIgnore(), s -> buildConfig.setTypeIgnore(s), regexes);
updateRegexes(() -> buildConfig.getTypeIgnore(), s -> buildConfig.setTypeIgnore(s), regexes);
return this;
}
......@@ -71,44 +71,45 @@ import java.lang.String;aspect GenerationFrontend {
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder excludeTokens(String... regexes) {
updateIgnored(() -> buildConfig.getTokenIgnore(), s -> buildConfig.setTokenIgnore(s), regexes);
updateRegexes(() -> buildConfig.getTokenIgnore(), s -> buildConfig.setTokenIgnore(s), regexes);
return this;
}
// not supported yet
public DumpBuilder includeAttributes(String... regexes) {
updateIgnored(() -> buildConfig.getAttributeIgnore(), s -> buildConfig.setAttributeIgnore(s), regexes);
updateRegexes(() -> buildConfig.getAttributeInclude(), s -> buildConfig.setAttributeInclude(s), regexes);
return this;
}
// not supported yet
public DumpBuilder includeNonterminalAttributes(String... regexes) {
// TODO
updateRegexes(() -> buildConfig.getNonterminalAttributeInclude(), s -> buildConfig.setNonterminalAttributeInclude(s), regexes);
return this;
}
/**
* Exclude every child whose name (i.e., context) matches at least on of the given regex strings.
* Unlike disabling types, the complete object and its (transitive) children won't be included in any output.
* This means, that the complete object and its (transitive) children will never be included in any output.
* @param regexes regex patterns to match child names
* @return this
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder excludeChildren(String... regexes) {
updateIgnored(() -> buildConfig.getChildIgnore(), s -> buildConfig.setChildIgnore(s), regexes);
updateRegexes(() -> buildConfig.getChildIgnore(), s -> buildConfig.setChildIgnore(s), regexes);
return this;
}
/**
* Exclude every relation whose role-name matches at least on of the given regex strings.
* Unlike disabling types, the complete object and its (transitive) children won't be included in any output, except.
* This means two things: a) the relation to any potential target object(s) is never shown, and b) the target
* object(s) are not shown unless they are reachable by another relation or by containment.
* @param regexes regex patterns to match child names
* @return this
* @see java.util.regex.Pattern#compile(java.lang.String)
*/
public DumpBuilder excludeRelations(String... regexes) {
updateIgnored(() -> buildConfig.getRelationIgnore(), s -> buildConfig.setRelationIgnore(s), regexes);
updateRegexes(() -> buildConfig.getRelationIgnore(), s -> buildConfig.setRelationIgnore(s), regexes);
return this;
}
private void updateIgnored(java.util.function.Supplier<String> getter, java.util.function.Consumer<String> setter, String... values) {
private void updateRegexes(java.util.function.Supplier<String> getter, java.util.function.Consumer<String> setter, String... values) {
for (String value : values) {
if (getter.get().isEmpty()) {
setter.accept(value);
......@@ -209,28 +210,59 @@ import java.lang.String;aspect GenerationFrontend {
}
aspect GenerationBackend {
class DumpAst {
private enum Source {
RELATION, INVISIBLE_PARENT, PARENT, ROOT
}
}
// --- transform --- (need to be a method, because it alters the AST while traversing the object structure)
// maybe return type is unncessary
protected DumpNode DumpAst.transform(TransformationTransferInformation tti, Object obj)
throws java.lang.reflect.InvocationTargetException, IllegalAccessException, NoSuchMethodException {
DumpNode result = transform(tti, obj, Source.ROOT);
// post-process relationTargetsUnprocessed
boolean someAreUnprocessed = true;
while (someAreUnprocessed) {
someAreUnprocessed = false;
java.util.Map<DumpNode, Boolean> copy = new java.util.HashMap<>(tti.relationTargetsUnprocessed);
for (java.util.Map.Entry<DumpNode, Boolean> entry : copy.entrySet()) {
if (entry.getValue()) {
transform(tti, entry.getKey().getObject(), Source.ROOT);
someAreUnprocessed = true;
}
}
}
return result;
}
protected DumpNode DumpAst.transform(TransformationTransferInformation tti, Object obj, Source source)
throws java.lang.reflect.InvocationTargetException, IllegalAccessException, NoSuchMethodException {
if (obj == null) {
return null;
}
if (tti.transformed.containsKey(obj)) {
return tti.transformed.get(obj);
DumpNode node = tti.transformed.get(obj);
if (node != null) {
if (source == Source.RELATION) {
return node;
}
// tti.transformed.put(obj, null);
// return null;
DumpNode node = new DumpNode();
// either processing as parent, or later as root-node. so mark it as processed.
tti.relationTargetsUnprocessed.put(node, false);
} else {
node = new DumpNode();
node.setObject(obj);
node.setLabel(obj.getClass().getSimpleName() + "@" + obj.hashCode());
node.setName("node" + tti.transformed.size());
tti.transformed.put(obj, node);
this.addDumpNode(node);
if (matches(getBuildConfig().typeIgnorePattern(), obj.getClass().getSimpleName())) {
node.setInvisible(true);
}
if (node.isAstNode()) {
// do not process node further if coming from a relation
if (source == Source.RELATION) {
tti.relationTargetsUnprocessed.put(node, true);
return node;
}
if (source == Source.INVISIBLE_PARENT || matches(getBuildConfig().typeIgnorePattern(), obj.getClass().getSimpleName())) {
node.setInvisible(true);
}
// only caching node.analyseClass does not help, since we want to do this only once per class of a node
final ClassAnalysisResult car;
Class<?> clazz = obj.getClass();
......@@ -243,10 +275,11 @@ aspect GenerationBackend {
// -- singleChild --
for (java.lang.reflect.Method method : car.singleChildMethods) {
Object target = method.invoke(obj);
DumpNode targetNode = transform(tti, target);
String childName = car.names.get(method);
DumpNode targetNode = transform(tti, target, nextSource(source, matches(getBuildConfig().childIgnorePattern(), childName)));
if (target != null && targetNode != null) {
DumpNormalChildNode normalChild = new DumpNormalChildNode();
normalChild.setName(car.names.get(method));
normalChild.setName(childName);
normalChild.setDumpNode(targetNode);
node.addDumpChildNode(normalChild);
}
......@@ -255,9 +288,11 @@ aspect GenerationBackend {
for (java.lang.reflect.Method method : car.listChildMethods) {
Iterable<?> targetList = (Iterable<?>) method.invoke(obj);
DumpListChildNode listChild = new DumpListChildNode();
listChild.setName(car.names.get(method));
String childName = car.names.get(method);
boolean shouldBeInvisisble = matches(getBuildConfig().childIgnorePattern(), childName);
listChild.setName(childName);
for (Object target : targetList) {
DumpNode targetNode = transform(tti, target);
DumpNode targetNode = transform(tti, target, nextSource(source, shouldBeInvisisble));
if (target != null && targetNode != null) {
listChild.addInnerDumpNode(new InnerDumpNode(targetNode));
}
......@@ -269,7 +304,7 @@ aspect GenerationBackend {
// -- singleRelation --
for (java.lang.reflect.Method method : car.singleRelationMethods) {
Object target = method.invoke(obj);
DumpNode targetNode = transform(tti, target);
DumpNode targetNode = transform(tti, target, Source.RELATION);
if (target != null && targetNode != null) {
DumpNormalRelation normalRelation = new DumpNormalRelation();
normalRelation.setName(car.names.get(method));
......@@ -283,7 +318,7 @@ aspect GenerationBackend {
DumpListRelation listRelation = new DumpListRelation();
listRelation.setName(car.names.get(method));
for (Object target : targetList) {
DumpNode targetNode = transform(tti, target);
DumpNode targetNode = transform(tti, target, Source.RELATION);
if (target != null && targetNode != null) {
listRelation.addInnerDumpNode(new InnerDumpNode(targetNode));
}
......@@ -296,8 +331,10 @@ aspect GenerationBackend {
for (java.lang.reflect.Method method : car.tokenMethods) {
Object target = method.invoke(obj);
if (target != null) {
DumpNode targetNode = transform(tti, target);
DumpNode targetNode = transform(tti, target, Source.RELATION);
DumpToken token = null;
// TODO check, if Iterable.isAssignableFrom(target.getClass()).
// if so, check isAstNode for first non-null to add DumpReferenceToken's, otherwise DumpValueToken's
if (targetNode != null && targetNode.isAstNode()) {
token = new DumpReferenceToken().setValue(targetNode);
} else {
......@@ -317,6 +354,11 @@ aspect GenerationBackend {
return node;
}
private Source DumpAst.nextSource(Source currentSource, boolean shouldBeInvisible) {
return currentSource == Source.INVISIBLE_PARENT ? Source.INVISIBLE_PARENT :
(shouldBeInvisible ? Source.INVISIBLE_PARENT : Source.PARENT);
}
ClassAnalysisResult DumpNode.analyzeClass()
throws java.lang.reflect.InvocationTargetException, IllegalAccessException, NoSuchMethodException {
ClassAnalysisResult result = new ClassAnalysisResult();
......@@ -329,14 +371,11 @@ aspect GenerationBackend {
switch (simpleName) {
case "Child":
String singleChildName = invokeName(annotation);
if (!matches(buildConfig().childIgnorePattern(), singleChildName)) {
result.singleChildMethods.add(method);
result.names.put(method, singleChildName);
}
break;
case "OptChild":
String optChildName = invokeName(annotation);
if (!matches(buildConfig().childIgnorePattern(), optChildName)) {
try {
// the annotated method is "get???Opt", but we want "get???"
java.lang.reflect.Method realGetter = clazz.getMethod("get" + optChildName);
......@@ -346,14 +385,11 @@ aspect GenerationBackend {
System.err.println("Could not find getter for Opt-child " + optChildName + " in " + clazz.getName());
throw new RuntimeException(e);
}
}
break;
case "ListChild":
String listChildName = invokeName(annotation);
if (!matches(buildConfig().childIgnorePattern(), listChildName)) {
result.listChildMethods.add(method);
result.names.put(method, listChildName);
}
break;
case "Token":
// heuristic for relations
......@@ -390,8 +426,23 @@ aspect GenerationBackend {
}
break;
case "Attribute":
// TODO. check for isNTA=true. then check for whether target is instance of iterable. if so, add to listChildren, otherwise to singelChild
// TODO. if isNTA=false, then handle attribute
String attributeName = method.getName();
boolean isNTA = (boolean) annotation.annotationType().getMethod("isNTA").invoke(annotation);
if (isNTA) {
if (matches(buildConfig().ntaIncludePattern(), attributeName)) {
if (Iterable.class.isAssignableFrom(method.getReturnType())) {
result.listChildMethods.add(method);
result.names.put(method, attributeName + "()");
} else {
result.singleChildMethods.add(method);
result.names.put(method, attributeName + "()");
}
}
} else if (matches(buildConfig().attributeIncludePattern(), attributeName)) {
// normal attribute
result.tokenMethods.add(method);
result.names.put(method, attributeName + "()");
}
break;
}
}
......@@ -410,7 +461,8 @@ aspect GenerationBackend {
syn java.util.regex.Pattern BuildConfig.typeIgnorePattern() = java.util.regex.Pattern.compile(getTypeIgnore());
syn java.util.regex.Pattern BuildConfig.childIgnorePattern() = java.util.regex.Pattern.compile(getChildIgnore());
syn java.util.regex.Pattern BuildConfig.tokenIgnorePattern() = java.util.regex.Pattern.compile(getTokenIgnore());
syn java.util.regex.Pattern BuildConfig.attributeIgnorePattern() = java.util.regex.Pattern.compile(getAttributeIgnore());
syn java.util.regex.Pattern BuildConfig.attributeIncludePattern() = java.util.regex.Pattern.compile(getAttributeInclude());
syn java.util.regex.Pattern BuildConfig.ntaIncludePattern() = java.util.regex.Pattern.compile(getNonterminalAttributeInclude());
syn java.util.regex.Pattern BuildConfig.relationIgnorePattern() = java.util.regex.Pattern.compile(getRelationIgnore());
static boolean ASTNode.matches(java.util.regex.Pattern p, String input) {
return p.matcher(input).matches();
......@@ -468,6 +520,7 @@ aspect GenerationBackend {
class TransformationTransferInformation {
java.util.Map<Object, DumpNode> transformed = new java.util.HashMap<>();
java.util.Map<DumpNode, Boolean> relationTargetsUnprocessed = new java.util.HashMap<>();
java.util.Map<Class<?>, ClassAnalysisResult> classAnalysisResults = new java.util.HashMap<>();
}
......
......@@ -2,6 +2,8 @@ package de.tudresden.inf.st.jastadd.dumpAst;
import beaver.Parser;
import de.tudresden.inf.st.jastadd.dumpAst.ast.*;
import de.tudresden.inf.st.jastadd.dumpAst.ast.ASTNode;
import de.tudresden.inf.st.jastadd.dumpAst.ast.JastAddList;
import de.tudresden.inf.st.jastadd.grammar2uml.ast.*;
import de.tudresden.inf.st.jastadd.grammar2uml.parser.Grammar2UmlParser;
import de.tudresden.inf.st.jastadd.grammar2uml.scanner.Grammar2UmlScanner;
......@@ -16,6 +18,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static de.tudresden.inf.st.jastadd.dumpAst.SimpleMain.Kind.*;
......@@ -119,6 +122,7 @@ public class SimpleMain {
.disableTypes(".*Comment")
.dumpAsSource(Paths.get("temp.plantuml"))
.dumpAsSVG(Paths.get("temp.svg"));
System.out.println(Iterable.class.getMethods()[0].getReturnType());
}
private static void small() throws IOException {
......
......@@ -26,4 +26,7 @@ aspect Grammar {
result.add(inner);
return result;
}
syn int Root.simpleAttr() = 42;
syn A Root.referenceAttr() = getA();
}
......@@ -270,7 +270,7 @@ public class TestExcluded {
}
@Test
public void testChildrenDefault() throws IOException {
public void testChildrenDefault() {
/* Root
|- a
|- b - - -.
......@@ -286,7 +286,6 @@ public class TestExcluded {
}), null);
root.getA().getB().setOneA(root.getA().getMyC().getA());
Dumper.read(root).disableTypes("C").dumpAsPNG(Paths.get("test.png"));
List<DumpNode> nodes = TestUtils.dumpModel(root);
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(
ROOT_NAME, A_NAME, A2_Name, B_NAME, B2_NAME, C_NAME);
......@@ -295,7 +294,6 @@ public class TestExcluded {
tuple("MyC", C_NAME), tuple("B", B_NAME));
}
@Disabled("a2 and b2 are included in output, so currently not working as intended")
@Test
public void testChildrenExclude() {
/* Root
......
package de.tudresden.inf.st.jastadd.testDumper;
import de.tudresden.inf.st.jastadd.dumpAst.ast.DumpNode;
import org.jastadd.testDumper.ast.Root;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.util.List;
import static de.tudresden.inf.st.jastadd.testDumper.TestUtils.*;
import static org.assertj.core.api.Assertions.*;
public class TestIncluded {
@Test
public void testValueAttributeDefault() {
Root root = createRoot(null, null);
List<DumpNode> nodes = TestUtils.dumpModel(root);
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME);
DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME);
assertThat(valueTokens(actualRoot)).containsOnly(entry("Name", ROOT_NAME));
}
@Test
public void testValueAttributeIncluded() {
Root root = createRoot(null, null);
List<DumpNode> nodes = TestUtils.dumpModel(root, db -> db.includeAttributes("simpleAttr"));
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME);
DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME);
assertThat(valueTokens(actualRoot)).containsOnly(entry("Name", ROOT_NAME), entry("simpleAttr()", 42));
}
@Test
public void testReferenceAttributeDefault() {
Root root = createRoot(createA(A_NAME), null);
List<DumpNode> nodes = TestUtils.dumpModel(root);
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME, A_NAME);
DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME);
assertThat(referenceTokens(actualRoot)).isEmpty();
}
@Test
public void testReferenceAttributeIncluded() {
Root root = createRoot(createA(A_NAME), null);
List<DumpNode> nodes = TestUtils.dumpModel(root, db -> db.includeAttributes("referenceAttr"));
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME, A_NAME);
DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME);
assertThatMapOf(referenceTokens(actualRoot)).containsOnly(tuple("referenceAttr()", A_NAME));
}
@Test
public void testNormalNTADefault() {
Root root = createRoot(null, createC(C_NAME));
List<DumpNode> nodes = TestUtils.dumpModel(root);
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME, C_NAME);
DumpNode actualC = TestUtils.findByName(nodes, C_NAME);
assertThatMapOf(normalChildren(actualC)).isEmpty();
}
@Test
public void testNormalNTAIncluded() {
Root root = createRoot(null, createC(C_NAME));
List<DumpNode> nodes = TestUtils.dumpModel(root, db -> db.includeNonterminalAttributes("getCalculated"));
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME, C_NAME, "Calculated-" + C_NAME);
DumpNode actualC = TestUtils.findByName(nodes, C_NAME);
assertThatMapOf(normalChildren(actualC)).containsOnly(tuple("getCalculated()", "Calculated-" + C_NAME));
}
@Test
public void testListNTADefault() {
Root root = createRoot(null, createC(C_NAME));
List<DumpNode> nodes = TestUtils.dumpModel(root);
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME, C_NAME);
DumpNode actualC = TestUtils.findByName(nodes, C_NAME);
assertThat(listChildren(actualC)).isEmpty();
}
@Disabled("NTA lists not working at the moment")
@Test
public void testListNTAIncluded() {
// TODO make the test not failing
Root root = createRoot(null, createC(C_NAME));
List<DumpNode> nodes = TestUtils.dumpModel(root, db -> db.includeNonterminalAttributes("AlsoCalculated"));
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactly(ROOT_NAME, C_NAME, "AlsoCalculated-" + C_NAME);
DumpNode actualC = TestUtils.findByName(nodes, C_NAME);
assertThatMapOf(listChildren(actualC), "getAlsoCalculated()").containsExactly("AlsoCalculated-" + C_NAME);
}
}
......@@ -30,7 +30,6 @@ public class TestSimple {
Root root = createRoot(createA(A_NAME), null);
List<DumpNode> nodes = TestUtils.dumpModel(root);
assertEquals(2, nodes.size());
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME);
DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME);
assertEquals(1, actualRoot.getNumDumpToken());
......@@ -57,7 +56,6 @@ public class TestSimple {
Root root = createRoot(null, createC(C_NAME));
List<DumpNode> nodes = TestUtils.dumpModel(root);
assertEquals(2, nodes.size());
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, C_NAME);
DumpNode actualRoot = TestUtils.findByName(nodes, ROOT_NAME);
assertEquals(1, actualRoot.getNumDumpToken());
......@@ -72,7 +70,7 @@ public class TestSimple {
root.getB(0).setOneA(root.getA());
List<DumpNode> nodes = TestUtils.dumpModel(root);
assertEquals(4, nodes.size());
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME, B_NAME, C_NAME);
DumpNode actualB = TestUtils.findByName(nodes, B_NAME);
assertThatMapOf(normalRelationChildren(actualB)).containsExactlyInAnyOrder(tuple("OneA", A_NAME));
}
......@@ -97,7 +95,7 @@ public class TestSimple {
root.getB(0).setMaybeC(root.getC());
List<DumpNode> nodes = TestUtils.dumpModel(root);
assertEquals(4, nodes.size());
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME, B_NAME, C_NAME);
DumpNode actualB = TestUtils.findByName(nodes, B_NAME);
assertThatMapOf(normalRelationChildren(actualB)).containsExactlyInAnyOrder(tuple("MaybeC", C_NAME));
}
......@@ -108,7 +106,7 @@ public class TestSimple {
root.getC().setBiA1(root.getA());
List<DumpNode> nodes = TestUtils.dumpModel(root);
assertEquals(4, nodes.size());
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME, B_NAME, C_NAME);
// bidirectional relations are currently not found, instead there will be two unidirectional ones
DumpNode actualA = TestUtils.findByName(nodes, A_NAME);
assertThatMapOf(normalRelationChildren(actualA)).containsExactlyInAnyOrder(tuple("BiC1", C_NAME));
......@@ -122,7 +120,7 @@ public class TestSimple {
root.getC().addBiA2(root.getA());
List<DumpNode> nodes = TestUtils.dumpModel(root);
assertEquals(4, nodes.size());
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME, B_NAME, C_NAME);
// bidirectional relations are currently not found, instead there will be two unidirectional ones
DumpNode actualA = TestUtils.findByName(nodes, A_NAME);
assertThatMapOf(normalRelationChildren(actualA)).containsExactlyInAnyOrder(tuple("BiC2", C_NAME));
......@@ -136,7 +134,7 @@ public class TestSimple {
root.getC().setBiA3(root.getA());
List<DumpNode> nodes = TestUtils.dumpModel(root);
assertEquals(4, nodes.size());
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME, B_NAME, C_NAME);
// bidirectional relations are currently not found, instead there will be two unidirectional ones
DumpNode actualA = TestUtils.findByName(nodes, A_NAME);
assertThatMapOf(normalRelationChildren(actualA)).containsExactlyInAnyOrder(tuple("BiC3", C_NAME));
......@@ -150,7 +148,7 @@ public class TestSimple {
root.getC().setRawReference(root.getA());
List<DumpNode> nodes = TestUtils.dumpModel(root);
assertEquals(4, nodes.size());
assertThat(nodes).flatExtracting(NAME_EXTRACTOR).containsExactlyInAnyOrder(ROOT_NAME, A_NAME, B_NAME, C_NAME);
DumpNode actualC = TestUtils.findByName(nodes, C_NAME);
assertThatMapOf(referenceTokens(actualC)).containsExactlyInAnyOrder(tuple(TOKEN_LABEL_RAW_REFERENCE, A_NAME));
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment