This is an automated email from the ASF dual-hosted git repository. ntimofeev pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 7bac798fb3893f19965a5f936b774daed920a98c Author: Andrus Adamchik <and...@objectstyle.com> AuthorDate: Sun Nov 13 11:36:50 2022 +0100 CAY-2774 Overriding service ordering in DI List causes DIRuntimeException --- .../java/org/apache/cayenne/di/spi/DIGraph.java | 1 + .../org/apache/cayenne/di/spi/DIGraphTest.java | 5 +- .../di/spi/DefaultInjectorInjectionTest.java | 85 ++++++++++++++-------- 3 files changed, 60 insertions(+), 31 deletions(-) diff --git a/cayenne-di/src/main/java/org/apache/cayenne/di/spi/DIGraph.java b/cayenne-di/src/main/java/org/apache/cayenne/di/spi/DIGraph.java index 2bd921349..e2678e9d5 100644 --- a/cayenne-di/src/main/java/org/apache/cayenne/di/spi/DIGraph.java +++ b/cayenne-di/src/main/java/org/apache/cayenne/di/spi/DIGraph.java @@ -68,6 +68,7 @@ class DIGraph<V> { public void add(V from, V to) { this.add(from); this.add(to); + neighbors.get(to).remove(from); neighbors.get(from).add(to); } diff --git a/cayenne-di/src/test/java/org/apache/cayenne/di/spi/DIGraphTest.java b/cayenne-di/src/test/java/org/apache/cayenne/di/spi/DIGraphTest.java index 78fef24ee..0d391e8b0 100644 --- a/cayenne-di/src/test/java/org/apache/cayenne/di/spi/DIGraphTest.java +++ b/cayenne-di/src/test/java/org/apache/cayenne/di/spi/DIGraphTest.java @@ -39,12 +39,13 @@ public class DIGraphTest { assertEquals(asList("y", "a", "z", "x"), sorted); } - @Test(expected = DIRuntimeException.class) + @Test public void testTopSortDirectCycle() { DIGraph<String> graph = new DIGraph<>(); graph.add("x", "y"); graph.add("y", "x"); - graph.topSort(); + List<String> sorted = graph.topSort(); + assertEquals(asList("x", "y"), sorted); } @Test(expected = DIRuntimeException.class) diff --git a/cayenne-di/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorInjectionTest.java b/cayenne-di/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorInjectionTest.java index 79741c607..85ff91512 100644 --- a/cayenne-di/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorInjectionTest.java +++ b/cayenne-di/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorInjectionTest.java @@ -20,29 +20,7 @@ package org.apache.cayenne.di.spi; import org.apache.cayenne.di.Key; import org.apache.cayenne.di.Module; -import org.apache.cayenne.di.mock.MockImplementation1; -import org.apache.cayenne.di.mock.MockImplementation1Alt; -import org.apache.cayenne.di.mock.MockImplementation1Alt2; -import org.apache.cayenne.di.mock.MockImplementation1_ListConfiguration; -import org.apache.cayenne.di.mock.MockImplementation1_ListConfigurationMock5; -import org.apache.cayenne.di.mock.MockImplementation1_MapConfiguration; -import org.apache.cayenne.di.mock.MockImplementation1_MapWithWildcards; -import org.apache.cayenne.di.mock.MockImplementation1_WithInjector; -import org.apache.cayenne.di.mock.MockImplementation2; -import org.apache.cayenne.di.mock.MockImplementation2Sub1; -import org.apache.cayenne.di.mock.MockImplementation2_ConstructorProvider; -import org.apache.cayenne.di.mock.MockImplementation2_ListConfiguration; -import org.apache.cayenne.di.mock.MockImplementation2_Named; -import org.apache.cayenne.di.mock.MockImplementation3; -import org.apache.cayenne.di.mock.MockImplementation4; -import org.apache.cayenne.di.mock.MockImplementation4Alt; -import org.apache.cayenne.di.mock.MockImplementation4Alt2; -import org.apache.cayenne.di.mock.MockImplementation5; -import org.apache.cayenne.di.mock.MockInterface1; -import org.apache.cayenne.di.mock.MockInterface2; -import org.apache.cayenne.di.mock.MockInterface3; -import org.apache.cayenne.di.mock.MockInterface4; -import org.apache.cayenne.di.mock.MockInterface5; +import org.apache.cayenne.di.mock.*; import org.junit.Test; import java.util.ArrayList; @@ -185,7 +163,7 @@ public class DefaultInjectorInjectionTest { public void testMapInjection() { Module module = binder -> { binder.bind(MockInterface1.class).to(MockImplementation1_MapConfiguration.class); - binder.bindMap(Object.class,"xyz") + binder.bindMap(Object.class, "xyz") .put("x", "xvalue").put("y", "yvalue").put("x", "xvalue1"); }; @@ -209,7 +187,7 @@ public class DefaultInjectorInjectionTest { // Key.get(new TypeLiteral<String, Class<?>>(){}); Map mapUntyped = injector.getInstance(Key.getMapOf(String.class, Class.class)); @SuppressWarnings("unchecked") - Map<String, Class<?>> map = (Map<String, Class<?>>)mapUntyped; + Map<String, Class<?>> map = (Map<String, Class<?>>) mapUntyped; assertNotNull(map); assertEquals(3, map.size()); @@ -225,9 +203,9 @@ public class DefaultInjectorInjectionTest { Module module = binder -> { binder.bind(MockInterface1.class).to(MockImplementation1_MapConfiguration.class); // bind 1 - binder.bindMap(Object.class,"xyz").put("x", "xvalue").put("y", "yvalue"); + binder.bindMap(Object.class, "xyz").put("x", "xvalue").put("y", "yvalue"); // second binding attempt to the same map... - binder.bindMap(Object.class,"xyz").put("z", "zvalue").put("x", "xvalue1"); + binder.bindMap(Object.class, "xyz").put("z", "zvalue").put("x", "xvalue1"); }; DefaultInjector injector = new DefaultInjector(module); @@ -312,6 +290,55 @@ public class DefaultInjectorInjectionTest { assertEquals(";1value;2value;3value;xyz;5value", service.getName()); } + @Test + public void testListInjection_Instance_addOverrideValueOrdering() { + + Integer i = Integer.valueOf(5); + + Module m1 = binder -> { + binder.bind(MockInterface1.class).to(MockImplementation1_ListConfiguration.class); + binder.bind(MockInterface5.class).to(MockImplementation5.class); + binder.bind(Integer.class).toInstance(i); + + binder.bindList(Object.class, "xyz") + .addAfter(i, MockInterface5.class) + .add(MockInterface5.class); + }; + + Module m2 = binder -> + binder.bindList(Object.class, "xyz").insertBefore(i, MockInterface5.class); + + // instance is inserted multiple types, as each instance is treated as a standalone DI Key + DefaultInjector i1 = new DefaultInjector(m1, m2); + assertEquals(";5;xyz;5", i1.getInstance(MockInterface1.class).getName()); + + DefaultInjector i2 = new DefaultInjector(m2, m1); + assertEquals(";5;xyz;5", i2.getInstance(MockInterface1.class).getName()); + } + + @Test + public void testListInjection_Type_addOverrideValueOrdering() { + + Module m1 = binder -> { + binder.bind(MockInterface1.class).to(MockImplementation1_ListConfiguration.class); + binder.bind(MockInterface5.class).to(MockImplementation5.class); + binder.bind(String.class).toInstance("a"); + + binder.bindList(Object.class, "xyz") + .addAfter(String.class, MockInterface5.class) + .add(MockInterface5.class); + }; + + Module m2 = binder -> binder.bindList(Object.class, "xyz") + .insertBefore(String.class, MockInterface5.class); + + DefaultInjector i1 = new DefaultInjector(m1, m2); + assertEquals(";a;xyz", i1.getInstance(MockInterface1.class).getName()); + + DefaultInjector i2 = new DefaultInjector(m2, m1); + assertEquals(";xyz;a", i2.getInstance(MockInterface1.class).getName()); + } + @Test public void testListInjection_addAllValues() { Module module = binder -> { @@ -399,7 +426,7 @@ public class DefaultInjectorInjectionTest { public void testListInjection_empty() { Module module = binder -> { binder.bind(MockInterface1.class).to(MockImplementation1_ListConfiguration.class); - binder.bindList(Object.class,"xyz"); + binder.bindList(Object.class, "xyz"); }; DefaultInjector injector = new DefaultInjector(module); @@ -432,7 +459,7 @@ public class DefaultInjectorInjectionTest { binder.bind(MockInterface2.class).to(MockImplementation2_ListConfiguration.class); // Bind list for MockImplementation2_ListConfiguration - binder.bindList(Object.class,"xyz") + binder.bindList(Object.class, "xyz") .add("xvalue") .add("yvalue") .add(MockImplementation5.class);