You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2022/11/15 14:27:25 UTC

[cayenne] 01/03: CAY-2774 Overriding service ordering in DI List causes DIRuntimeException

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 <an...@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);