diff --git a/.gitignore b/.gitignore index 0ce1ed6d4729d8351479cdf3f2df31e9f9f16d7d..dd288580ab6963cbac2a1795fccf901264833749 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,6 @@ src/test/jastadd/multiple/Multiple.ast src/test/jastadd/multiple/Multiple.jadd src/test/jastadd/resolver/Resolver.ast src/test/jastadd/resolver/Resolver.jadd -src/test/jastadd/resolver/ResolverRefResolver.jadd \ No newline at end of file +src/test/jastadd/resolver/ResolverRefResolver.jadd +src/test/jastadd/listnames/ListNames.ast +src/test/jastadd/listnames/ListNames.jadd \ No newline at end of file diff --git a/build.gradle b/build.gradle index 347c375e2fd4c9b1253248ba0590da68428e4776..fdf2acc274d909b8a9436cf2ffbf72e1b253f379 100644 --- a/build.gradle +++ b/build.gradle @@ -182,7 +182,7 @@ task compileMultipleTest(type: JavaExec, group: 'verification') { task preprocessResolverTest(type: JavaExec, group: 'verification') { doFirst { - delete 'src/test/jastadd/resolver/Resolver.ast', 'src/test/jastadd/resolver/Resolver.jadd' + delete 'src/test/jastadd/resolver/Resolver.ast', 'src/test/jastadd/resolver/Resolver.jadd', 'src/test/jastadd/resolver/ResolverRefResolver.jadd' } classpath = sourceSets.main.runtimeClasspath @@ -201,6 +201,28 @@ task compileResolverTest(type: JavaExec, group: 'verification') { args '--o=src/test/java-gen/', '--package=resolver.ast', 'src/test/jastadd/resolver/Resolver.ast', 'src/test/jastadd/resolver/Resolver.jadd', 'src/test/jastadd/resolver/ResolverUtils.jadd', 'src/test/jastadd/resolver/ResolverRefResolver.jadd', 'src/test/jastadd/resolver/MyRefResolver.jadd', 'src/test/jastadd/Utils.jadd' } +task preprocessListNamesTest(type: JavaExec, group: 'verification') { + + doFirst { + delete 'src/test/jastadd/listnames/ListNames.ast', 'src/test/jastadd/listnames/ListNames.jadd' + } + + classpath = sourceSets.main.runtimeClasspath + main = 'org.jastadd.relast.compiler.Compiler' + args 'src/test/jastadd/listnames/ListNames.relast', '--file', '--grammarName=src/test/jastadd/listnames/ListNames', '--jastAddList=ListyMcListface' +} + +task compileListNamesTest(type: JavaExec, group: 'verification') { + + doFirst { + delete 'src/test/java-gen/listnames' + } + + classpath = sourceSets.main.runtimeClasspath + main = 'org.jastadd.JastAdd' + args '--o=src/test/java-gen/', '--package=listnames.ast', 'src/test/jastadd/listnames/ListNames.ast', 'src/test/jastadd/listnames/ListNames.jadd', 'src/test/jastadd/Utils.jadd', '--List=ListyMcListface' +} + test { outputs.upToDateWhen { false } @@ -219,4 +241,7 @@ test.dependsOn compileMultipleTest compileMultipleTest.dependsOn preprocessMultipleTest test.dependsOn compileResolverTest -compileResolverTest.dependsOn preprocessResolverTest \ No newline at end of file +compileResolverTest.dependsOn preprocessResolverTest + +test.dependsOn compileListNamesTest +compileListNamesTest.dependsOn preprocessListNamesTest \ No newline at end of file diff --git a/src/main/jastadd/Backend.jadd b/src/main/jastadd/Backend.jadd index e5261078d1f0bb922249942c89cf65c033f3420c..7e02ef026e8cbbb01b2a602f3f98bdbe4b57b018 100644 --- a/src/main/jastadd/Backend.jadd +++ b/src/main/jastadd/Backend.jadd @@ -1,7 +1,9 @@ aspect BackendAbstractGrammar { public static String ASTNode.listClass = "ArrayList"; - public static boolean ASTNode.resolverHelper = false; + public static String ASTNode.jastAddListType = "List"; + +public static boolean ASTNode.resolverHelper = false; public String Program.generateAbstractGrammar() { StringBuilder sb = new StringBuilder(); @@ -121,7 +123,7 @@ aspect BackendAspect { return getTypeUse() + " " + getID(); } public String ListComponent.constructorParameter() { - return "List<" + getTypeUse() + "> " + getID(); + return ASTNode.jastAddListType + "<" + getTypeUse() + "> " + getID(); } public String OptComponent.constructorParameter() { return "Opt<" + getTypeUse() + "> " + getID(); diff --git a/src/main/java/org/jastadd/relast/compiler/Compiler.java b/src/main/java/org/jastadd/relast/compiler/Compiler.java index 0eee7309ebf85a2c53c99c07ba00a069ddae07b0..84fb2a7480536a8689be5153ffb293ca18be609a 100644 --- a/src/main/java/org/jastadd/relast/compiler/Compiler.java +++ b/src/main/java/org/jastadd/relast/compiler/Compiler.java @@ -19,6 +19,7 @@ public class Compiler { private FlagOption optionWriteToFile; private FlagOption optionPrintAST; private StringOption optionListClass; + private StringOption optionJastAddList; private StringOption optionGrammarName; private FlagOption optionResolverHelper; private CommandLine commandLine; @@ -38,6 +39,12 @@ public class Compiler { List<TypeDecl> unresolvedDecls = new ArrayList<>(); Program p = parseProgram(filenames); + if (optionJastAddList.isSet()) { + System.out.println("JastAdd List type is set to " + optionJastAddList.getValue()); + ASTNode.jastAddListType = optionJastAddList.getValue(); + } + + if (optionResolverHelper.isSet()) { // get a list of all (abstract or not) non-terminals List<TypeDecl> nonTerminals = new ArrayList<>(); @@ -122,6 +129,8 @@ public class Compiler { optionListClass = addOption(new StringOption("listClass", "determine the class name of the nonterminal reference list")); optionGrammarName = addOption(new StringOption("grammarName", "name of the generated grammar and aspect (without file extension)")); optionResolverHelper = addOption(new FlagOption("resolverHelper", "create a subtype for each type containing a string that can be used to resolve the type later")); + optionJastAddList = addOption(new StringOption("jastAddList", "set the name of the List type in JastAdd (has to match the option '--List' or its default List)")); + } private <OptionType extends Option<?>> OptionType addOption(OptionType option) { diff --git a/src/test/jastadd/listnames/ListNames.relast b/src/test/jastadd/listnames/ListNames.relast new file mode 100644 index 0000000000000000000000000000000000000000..b620c6b8e5cb2800d7afa575a566bb0a2666894a --- /dev/null +++ b/src/test/jastadd/listnames/ListNames.relast @@ -0,0 +1,20 @@ +Root ::= A* B*; +A ::= <Name>; +B ::= <Name>; +rel Root.Aa? -> A; + +rel A.Di1 -> B; +rel A.Di2? -> B; +rel A.Di3* -> B; + +rel A.Bi1 <-> B.Bi1; +rel A.Bi2 <-> B.Bi2?; +rel A.Bi3 <-> B.Bi3*; + +rel A.Bi4? <-> B.Bi4; +rel A.Bi5? <-> B.Bi5?; +rel A.Bi6? <-> B.Bi6*; + +rel A.Bi7* <-> B.Bi7; +rel A.Bi8* <-> B.Bi8?; +rel A.Bi9* <-> B.Bi9*; diff --git a/src/test/java/org/jastadd/relast/tests/ListNames.java b/src/test/java/org/jastadd/relast/tests/ListNames.java new file mode 100644 index 0000000000000000000000000000000000000000..3ddd9e5c80d0c461f6de291d9e0f0c61835db093 --- /dev/null +++ b/src/test/java/org/jastadd/relast/tests/ListNames.java @@ -0,0 +1,641 @@ +package org.jastadd.relast.tests; + +import listnames.ast.A; +import listnames.ast.B; +import listnames.ast.Root; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Arrays; + +import static org.jastadd.relast.tests.TestHelpers.readFile; +import static org.junit.jupiter.api.Assertions.*; + + +@SuppressWarnings("ArraysAsListWithZeroOrOneArgument") +class ListNames { + private Root r; + private A a1; + private A a2; + private A a3; + private B b1; + private B b2; + private B b3; + + + @Test + void checkListNames() throws IOException { + + String aspectFile = "./src/test/jastadd/listnames/ListNames.jadd"; + String aspect = readFile(aspectFile, Charset.defaultCharset()); + + int index = 0; + int count = 0; + while (aspect.indexOf("ListyMcListface", index) >= 0) { + count++; + index = aspect.indexOf("ListyMcListface", index) + "ListyMcListface".length(); + } + + // ListyMcListface must occur exactly twice (in the constructor for Root) + assertSame(2, count); + + } + + + /** + * rel A.Di1 -> B; + */ + @Test + void testDi1() { + setup(); + a1.setDi1(b2); + a2.setDi1(b1); + + assertSame(a1.getDi1(), b2); + assertSame(a2.getDi1(), b1); + + a2.setDi1(b2); + + assertSame(a1.getDi1(), b2); + assertSame(a2.getDi1(), b2); + + try { + a3.setDi1(null); + fail("should throw an exception"); + } catch (Exception e) { + // OK + } + } + + + /** + * rel A.Di2? -> B; + */ + @Test + void testDi2() { + setup(); + a1.setDi2(b2); + a2.setDi2(b1); + + assertSame(a1.getDi2(), b2); + assertSame(a2.getDi2(), b1); + + a2.setDi2(b2); + + assertSame(a1.getDi2(), b2); + assertSame(a2.getDi2(), b2); + + a2.clearDi2(); + + assertSame(a1.getDi2(), b2); + assertNull(a2.getDi2()); + + assertTrue(a1.hasDi2()); + assertFalse(a2.hasDi2()); + assertFalse(a3.hasDi2()); + } + + + /** + * rel A.Di3* -> B; + */ + @Test + void testDi3() { + setup(); + a1.addDi3(b1); + a1.addDi3(b2); + a1.addDi3(b3); + a2.addDi3(b2); + + assertEquals(a1.getDi3s(), Arrays.asList(b1, b2, b3)); + assertEquals(a1.getDi3List(), Arrays.asList(b1, b2, b3)); + assertEquals(a2.getDi3s(), Arrays.asList(b2)); + assertEquals(a2.getDi3List(), Arrays.asList(b2)); + assertEquals(a3.getDi3s(), Arrays.asList()); + assertEquals(a3.getDi3List(), Arrays.asList()); + + a1.addDi3(b1); + a2.addDi3(b1); + a2.addDi3(b2); + + assertEquals(a1.getDi3s(), Arrays.asList(b1, b2, b3, b1)); + assertEquals(a1.getDi3List(), Arrays.asList(b1, b2, b3, b1)); + assertEquals(a2.getDi3s(), Arrays.asList(b2, b1, b2)); + assertEquals(a2.getDi3List(), Arrays.asList(b2, b1, b2)); + assertEquals(a3.getDi3s(), Arrays.asList()); + assertEquals(a3.getDi3List(), Arrays.asList()); + + a1.removeDi3(b1); + a2.removeDi3(b2); + + assertEquals(a1.getDi3s(), Arrays.asList(b2, b3, b1)); + assertEquals(a1.getDi3List(), Arrays.asList(b2, b3, b1)); + assertEquals(a2.getDi3s(), Arrays.asList(b1, b2)); + assertEquals(a2.getDi3List(), Arrays.asList(b1, b2)); + assertEquals(a3.getDi3s(), Arrays.asList()); + assertEquals(a3.getDi3List(), Arrays.asList()); + } + + + /** + * rel A.Bi1 <-> B.Bi1; + */ + + + @Test + void testBi11() { + // Init + setup(); + a1.setBi1(b1); + a2.setBi1(b2); + + // Change + a2.setBi1(b1); + + assertNull(a1.getBi1()); + assertSame(a2.getBi1(), b1); + assertSame(b1.getBi1(), a2); + assertNull(b2.getBi1()); + } + + @Test + void testBi12() { + // Init + setup(); + a1.setBi1(b2); + + // Change + a2.setBi1(b2); + + assertNull(a1.getBi1()); + assertSame(a2.getBi1(), b2); + assertNull(b1.getBi1()); + assertSame(b2.getBi1(), a2); + } + + + /** + * rel A.Bi2 <-> B.Bi2?; + */ + + @Test + void testBi21() { + // Init + setup(); + a1.setBi2(b1); + a2.setBi2(b2); + + // Change + a2.setBi2(b1); + + assertNull(a1.getBi2()); + assertSame(a2.getBi2(), b1); + assertSame(b1.getBi2(), a2); + assertNull(b2.getBi2()); + } + + @Test + void testBi22() { + // Init + setup(); + a1.setBi2(b2); + + // Change + a2.setBi2(b2); + + assertNull(a1.getBi2()); + assertSame(a2.getBi2(), b2); + assertNull(b1.getBi2()); + assertSame(b2.getBi2(), a2); + } + + + /** + * rel A.Bi3 <-> B.Bi3*; + */ + @Test + void testBi3() { + setup(); + a2.setBi3(b2); + + assertNull(a1.getBi3()); + assertSame(a2.getBi3(), b2); + assertEquals(b1.getBi3s(), Arrays.asList()); + assertEquals(b1.getBi3List(), Arrays.asList()); + assertEquals(b2.getBi3s(), Arrays.asList(a2)); + assertEquals(b2.getBi3List(), Arrays.asList(a2)); + assertEquals(b3.getBi3s(), Arrays.asList()); + assertEquals(b3.getBi3List(), Arrays.asList()); + + a2.setBi3(b3); + + assertNull(a1.getBi3()); + assertSame(a2.getBi3(), b3); + assertEquals(b1.getBi3s(), Arrays.asList()); + assertEquals(b1.getBi3List(), Arrays.asList()); + assertEquals(b2.getBi3s(), Arrays.asList()); + assertEquals(b2.getBi3List(), Arrays.asList()); + assertEquals(b3.getBi3s(), Arrays.asList(a2)); + assertEquals(b3.getBi3List(), Arrays.asList(a2)); + + a1.setBi3(b3); + a3.setBi3(b3); + + assertSame(a1.getBi3(), b3); + assertSame(a2.getBi3(), b3); + assertSame(a3.getBi3(), b3); + assertEquals(b1.getBi3s(), Arrays.asList()); + assertEquals(b1.getBi3List(), Arrays.asList()); + assertEquals(b2.getBi3s(), Arrays.asList()); + assertEquals(b2.getBi3List(), Arrays.asList()); + assertEquals(b3.getBi3s(), Arrays.asList(a2, a1, a3)); + assertEquals(b3.getBi3List(), Arrays.asList(a2, a1, a3)); + + a2.setBi3(b1); + + assertSame(a1.getBi3(), b3); + assertSame(a2.getBi3(), b1); + assertSame(a3.getBi3(), b3); + assertEquals(b1.getBi3s(), Arrays.asList(a2)); + assertEquals(b1.getBi3List(), Arrays.asList(a2)); + assertEquals(b2.getBi3s(), Arrays.asList()); + assertEquals(b2.getBi3List(), Arrays.asList()); + assertEquals(b3.getBi3s(), Arrays.asList(a1, a3)); + assertEquals(b3.getBi3List(), Arrays.asList(a1, a3)); + + try { + a2.setBi3(null); + fail("should throw an exception"); + } catch (Exception e) { + // OK + } + } + + + /** + * rel A.Bi4? <-> B.Bi4; + */ + @Test + void testBi41() { + // Init + setup(); + a1.setBi4(b1); + a2.setBi4(b2); + + // Change + a2.setBi4(b1); + + assertNull(a1.getBi4()); + assertSame(a2.getBi4(), b1); + assertSame(b1.getBi4(), a2); + assertNull(b2.getBi4()); + } + + @Test + void testBi42() { + // Init + setup(); + a1.setBi4(b2); + + // Change + a2.setBi4(b2); + + assertNull(a1.getBi4()); + assertSame(a2.getBi4(), b2); + assertNull(b1.getBi4()); + assertSame(b2.getBi4(), a2); + } + + + /** + * rel A.Bi5? <-> B.Bi5?; + */ + @Test + void testBi51() { + // Init + setup(); + a1.setBi5(b1); + a2.setBi5(b2); + + // Change + a2.setBi5(b1); + + assertNull(a1.getBi5()); + assertSame(a2.getBi5(), b1); + assertSame(b1.getBi5(), a2); + assertNull(b2.getBi5()); + } + + @Test + void testBi52() { + // Init + setup(); + a1.setBi5(b2); + + // Change + a2.setBi5(b2); + + assertNull(a1.getBi5()); + assertSame(a2.getBi5(), b2); + assertNull(b1.getBi5()); + assertSame(b2.getBi5(), a2); + } + + + /** + * rel A.Bi6? <-> B.Bi6*; + */ + @Test + void testBi6() { + setup(); + a2.setBi6(b2); + + assertNull(a1.getBi6()); + assertSame(a2.getBi6(), b2); + assertEquals(b1.getBi6s(), Arrays.asList()); + assertEquals(b1.getBi6List(), Arrays.asList()); + assertEquals(b2.getBi6s(), Arrays.asList(a2)); + assertEquals(b2.getBi6List(), Arrays.asList(a2)); + assertEquals(b3.getBi6s(), Arrays.asList()); + assertEquals(b3.getBi6List(), Arrays.asList()); + + a2.setBi6(b3); + + assertNull(a1.getBi6()); + assertSame(a2.getBi6(), b3); + assertEquals(b1.getBi6s(), Arrays.asList()); + assertEquals(b1.getBi6List(), Arrays.asList()); + assertEquals(b2.getBi6s(), Arrays.asList()); + assertEquals(b2.getBi6List(), Arrays.asList()); + assertEquals(b3.getBi6s(), Arrays.asList(a2)); + assertEquals(b3.getBi6List(), Arrays.asList(a2)); + + a1.setBi6(b3); + a3.setBi6(b3); + + assertSame(a1.getBi6(), b3); + assertSame(a2.getBi6(), b3); + assertSame(a3.getBi6(), b3); + assertEquals(b1.getBi6s(), Arrays.asList()); + assertEquals(b1.getBi6List(), Arrays.asList()); + assertEquals(b2.getBi6s(), Arrays.asList()); + assertEquals(b2.getBi6List(), Arrays.asList()); + assertEquals(b3.getBi6s(), Arrays.asList(a2, a1, a3)); + assertEquals(b3.getBi6List(), Arrays.asList(a2, a1, a3)); + + a2.setBi6(b1); + + assertSame(a1.getBi6(), b3); + assertSame(a2.getBi6(), b1); + assertSame(a3.getBi6(), b3); + assertEquals(b1.getBi6s(), Arrays.asList(a2)); + assertEquals(b1.getBi6List(), Arrays.asList(a2)); + assertEquals(b2.getBi6s(), Arrays.asList()); + assertEquals(b2.getBi6List(), Arrays.asList()); + assertEquals(b3.getBi6s(), Arrays.asList(a1, a3)); + assertEquals(b3.getBi6List(), Arrays.asList(a1, a3)); + + a2.clearBi6(); + + assertSame(a1.getBi6(), b3); + assertNull(a2.getBi6()); + assertSame(a3.getBi6(), b3); + assertEquals(b1.getBi6s(), Arrays.asList()); + assertEquals(b1.getBi6List(), Arrays.asList()); + assertEquals(b2.getBi6s(), Arrays.asList()); + assertEquals(b2.getBi6List(), Arrays.asList()); + assertEquals(b3.getBi6s(), Arrays.asList(a1, a3)); + assertEquals(b3.getBi6List(), Arrays.asList(a1, a3)); + + assertTrue(a1.hasBi6()); + assertFalse(a2.hasBi6()); + assertTrue(a3.hasBi6()); + } + + + /** + * rel A.Bi7* <-> B.Bi7; + */ + @Test + void testBi7() { + setup(); + a2.addBi7(b2); + + assertEquals(a1.getBi7s(), Arrays.asList()); + assertEquals(a1.getBi7List(), Arrays.asList()); + assertEquals(a2.getBi7s(), Arrays.asList(b2)); + assertEquals(a2.getBi7List(), Arrays.asList(b2)); + assertNull(b1.getBi7()); + assertSame(b2.getBi7(), a2); + assertNull(b3.getBi7()); + + a2.addBi7(b3); + a1.addBi7(b2); + + assertEquals(a1.getBi7s(), Arrays.asList(b2)); + assertEquals(a1.getBi7List(), Arrays.asList(b2)); + assertEquals(a2.getBi7s(), Arrays.asList(b3)); + assertEquals(a2.getBi7List(), Arrays.asList(b3)); + assertNull(b1.getBi7()); + assertSame(b2.getBi7(), a1); + assertSame(b3.getBi7(), a2); + + a1.addBi7(b1); + + assertEquals(a1.getBi7s(), Arrays.asList(b2, b1)); + assertEquals(a1.getBi7List(), Arrays.asList(b2, b1)); + assertEquals(a2.getBi7s(), Arrays.asList(b3)); + assertEquals(a2.getBi7List(), Arrays.asList(b3)); + assertSame(b1.getBi7(), a1); + assertSame(b2.getBi7(), a1); + assertSame(b3.getBi7(), a2); + + a1.addBi7(b1); + + assertEquals(a1.getBi7s(), Arrays.asList(b2, b1)); + assertEquals(a1.getBi7List(), Arrays.asList(b2, b1)); + assertEquals(a2.getBi7s(), Arrays.asList(b3)); + assertEquals(a2.getBi7List(), Arrays.asList(b3)); + assertSame(b1.getBi7(), a1); + assertSame(b2.getBi7(), a1); + assertSame(b3.getBi7(), a2); + + a1.removeBi7(b1); + + assertEquals(a1.getBi7s(), Arrays.asList(b2)); + assertEquals(a1.getBi7List(), Arrays.asList(b2)); + assertEquals(a2.getBi7s(), Arrays.asList(b3)); + assertEquals(a2.getBi7List(), Arrays.asList(b3)); + assertNull(b1.getBi7()); + assertSame(b2.getBi7(), a1); + assertSame(b3.getBi7(), a2); + } + + + /** + * rel A.Bi8* <-> B.Bi8?; + */ + @Test + void testBi8() { + setup(); + a2.addBi8(b2); + + assertEquals(a1.getBi8s(), Arrays.asList()); + assertEquals(a1.getBi8List(), Arrays.asList()); + assertEquals(a2.getBi8s(), Arrays.asList(b2)); + assertEquals(a2.getBi8List(), Arrays.asList(b2)); + assertNull(b1.getBi8()); + assertSame(b2.getBi8(), a2); + assertNull(b3.getBi8()); + + a2.addBi8(b3); + a1.addBi8(b2); + + assertEquals(a1.getBi8s(), Arrays.asList(b2)); + assertEquals(a1.getBi8List(), Arrays.asList(b2)); + assertEquals(a2.getBi8s(), Arrays.asList(b3)); + assertEquals(a2.getBi8List(), Arrays.asList(b3)); + assertNull(b1.getBi8()); + assertSame(b2.getBi8(), a1); + assertSame(b3.getBi8(), a2); + + a1.addBi8(b1); + + assertEquals(a1.getBi8s(), Arrays.asList(b2, b1)); + assertEquals(a1.getBi8List(), Arrays.asList(b2, b1)); + assertEquals(a2.getBi8s(), Arrays.asList(b3)); + assertEquals(a2.getBi8List(), Arrays.asList(b3)); + assertSame(b1.getBi8(), a1); + assertSame(b2.getBi8(), a1); + assertSame(b3.getBi8(), a2); + + a1.addBi8(b1); + + assertEquals(a1.getBi8s(), Arrays.asList(b2, b1)); + assertEquals(a1.getBi8List(), Arrays.asList(b2, b1)); + assertEquals(a2.getBi8s(), Arrays.asList(b3)); + assertEquals(a2.getBi8List(), Arrays.asList(b3)); + assertSame(b1.getBi8(), a1); + assertSame(b2.getBi8(), a1); + assertSame(b3.getBi8(), a2); + + a1.removeBi8(b1); + + assertEquals(a1.getBi8s(), Arrays.asList(b2)); + assertEquals(a1.getBi8List(), Arrays.asList(b2)); + assertEquals(a2.getBi8s(), Arrays.asList(b3)); + assertEquals(a2.getBi8List(), Arrays.asList(b3)); + assertNull(b1.getBi8()); + assertSame(b2.getBi8(), a1); + assertSame(b3.getBi8(), a2); + } + + + /** + * rel A.Bi9* <-> B.Bi9*; + */ + @Test + void testBi9() { + setup(); + a1.addBi9(b1); + a1.addBi9(b2); + + assertEquals(a1.getBi9s(), Arrays.asList(b1, b2)); + assertEquals(a1.getBi9List(), Arrays.asList(b1, b2)); + assertEquals(a2.getBi9s(), Arrays.asList()); + assertEquals(a2.getBi9List(), Arrays.asList()); + assertEquals(a3.getBi9s(), Arrays.asList()); + assertEquals(a3.getBi9List(), Arrays.asList()); + assertEquals(b1.getBi9s(), Arrays.asList(a1)); + assertEquals(b1.getBi9List(), Arrays.asList(a1)); + assertEquals(b2.getBi9s(), Arrays.asList(a1)); + assertEquals(b2.getBi9List(), Arrays.asList(a1)); + assertEquals(b3.getBi9s(), Arrays.asList()); + assertEquals(b3.getBi9List(), Arrays.asList()); + + b3.addBi9(a1); + b3.addBi9(a3); + b3.addBi9(a1); + + assertEquals(a1.getBi9s(), Arrays.asList(b1, b2, b3, b3)); + assertEquals(a1.getBi9List(), Arrays.asList(b1, b2, b3, b3)); + assertEquals(a2.getBi9s(), Arrays.asList()); + assertEquals(a2.getBi9List(), Arrays.asList()); + assertEquals(a3.getBi9s(), Arrays.asList(b3)); + assertEquals(a3.getBi9List(), Arrays.asList(b3)); + assertEquals(b1.getBi9s(), Arrays.asList(a1)); + assertEquals(b1.getBi9List(), Arrays.asList(a1)); + assertEquals(b2.getBi9s(), Arrays.asList(a1)); + assertEquals(b2.getBi9List(), Arrays.asList(a1)); + assertEquals(b3.getBi9s(), Arrays.asList(a1, a3, a1)); + assertEquals(b3.getBi9List(), Arrays.asList(a1, a3, a1)); + + b3.removeBi9(a1); + + assertEquals(a1.getBi9s(), Arrays.asList(b1, b2, b3)); + assertEquals(a1.getBi9List(), Arrays.asList(b1, b2, b3)); + assertEquals(a2.getBi9s(), Arrays.asList()); + assertEquals(a2.getBi9List(), Arrays.asList()); + assertEquals(a3.getBi9s(), Arrays.asList(b3)); + assertEquals(a3.getBi9List(), Arrays.asList(b3)); + assertEquals(b1.getBi9s(), Arrays.asList(a1)); + assertEquals(b1.getBi9List(), Arrays.asList(a1)); + assertEquals(b2.getBi9s(), Arrays.asList(a1)); + assertEquals(b2.getBi9List(), Arrays.asList(a1)); + assertEquals(b3.getBi9s(), Arrays.asList(a3, a1)); + assertEquals(b3.getBi9List(), Arrays.asList(a3, a1)); + } + + + @Test + void testImmutableList() { + setup(); + + a1.addDi3(b1); + a1.addDi3(b2); + try { + a1.getDi3s().add(b3); + fail("should throw an exception"); + } catch (Exception e) { + // OK + } + + a1.addBi7(b1); + a1.addBi7(b2); + try { + a1.getBi7s().add(b3); + fail("should throw an exception"); + } catch (Exception e) { + // OK + } + + a1.addBi9(b1); + a1.addBi9(b2); + try { + a1.getBi9s().add(b3); + fail("should throw an exception"); + } catch (Exception e) { + // OK + } + } + + @BeforeEach + void setup() { + r = new Root(); + a1 = new A("a1"); + a2 = new A("a2"); + a3 = new A("a3"); + b1 = new B("b1"); + b2 = new B("b2"); + b3 = new B("b3"); + + r.addA(a1); + r.addA(a2); + r.addA(a3); + r.addB(b1); + r.addB(b2); + r.addB(b3); + } +}