Improve RoutedDOMRpcRoutingTableEntryTest 54/97954/5
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 17 Oct 2021 10:52:18 +0000 (12:52 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Sun, 17 Oct 2021 14:36:54 +0000 (16:36 +0200)
The only test we had here was exercising a warning path, expand
the test suite to properly cover routed RPCs.

Change-Id: Ic37cdc54b1406257408505b21cb65d6d0aa1cf35
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
dom/mdsal-dom-broker/pom.xml
dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/RoutedDOMRpcRoutingTableEntryTest.java
dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/Rpcs.java
dom/mdsal-dom-broker/src/test/resources/rpcs.yang

index 6279d2328f6feb9b763394af1eb04298f818e96f..63e8c52176a35dc70385cc9b849a5c76e92c055c 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>mockito-configuration</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-test-util</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.mdsal</groupId>
             <artifactId>mdsal-dom-inmemory-datastore</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>yang-test-util</artifactId>
+            <groupId>org.opendaylight.mdsal</groupId>
+            <artifactId>yang-binding</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal.model</groupId>
+            <artifactId>yang-ext</artifactId>
+            <scope>test</scope>
         </dependency>
     </dependencies>
 
index be9198cd522214ec4408876d0d595f24bea3c3f9..e57809ad4ca7306dd0b81c2e8968b9f46708a931 100644 (file)
@@ -10,13 +10,16 @@ package org.opendaylight.mdsal.dom.broker;
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
-import static org.opendaylight.mdsal.dom.broker.TestUtils.TEST_CHILD;
+import static org.mockito.Mockito.verify;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
 import org.junit.Before;
@@ -24,40 +27,142 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
+import org.opendaylight.mdsal.dom.api.DOMRpcImplementation;
 import org.opendaylight.mdsal.dom.api.DOMRpcImplementationNotAvailableException;
+import org.opendaylight.mdsal.dom.api.DOMRpcResult;
 import org.opendaylight.mdsal.dom.broker.DOMRpcRouter.OperationInvocation;
-import org.opendaylight.mdsal.dom.broker.util.TestModel;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 
 @RunWith(MockitoJUnitRunner.StrictStubs.class)
 public class RoutedDOMRpcRoutingTableEntryTest {
-    @Mock
-    public RpcDefinition rpcDefinition;
+    public static final YangInstanceIdentifier CTX_IN_INPUT =
+        YangInstanceIdentifier.create(new NodeIdentifier(Rpcs.CTX));
+    public static final YangInstanceIdentifier ONE_PATH = YangInstanceIdentifier.create(
+        new NodeIdentifier(Rpcs.BAZ), NodeIdentifierWithPredicates.of(Rpcs.BAZ, Rpcs.NAME, "one"));
+    public static final YangInstanceIdentifier TWO_PATH = YangInstanceIdentifier.create(
+        new NodeIdentifier(Rpcs.BAZ), NodeIdentifierWithPredicates.of(Rpcs.BAZ, Rpcs.NAME, "two"));
+
+    public static final ContainerNode ONE_INPUT = Builders.containerBuilder()
+        .withNodeIdentifier(new NodeIdentifier(Rpcs.INPUT))
+        .withChild(ImmutableNodes.leafNode(Rpcs.CTX, ONE_PATH))
+        .build();
+    public static final ContainerNode TWO_INPUT = Builders.containerBuilder()
+        .withNodeIdentifier(new NodeIdentifier(Rpcs.INPUT))
+        .withChild(ImmutableNodes.leafNode(Rpcs.CTX, TWO_PATH))
+        .build();
+    public static final ContainerNode GLOBAL_INPUT = Builders.containerBuilder()
+        .withNodeIdentifier(new NodeIdentifier(Rpcs.INPUT))
+        // This not covered by schema
+        .withChild(ImmutableNodes.leafNode(Rpcs.NAME, "name"))
+        .build();
 
-    private RoutedDOMRpcRoutingTableEntry entry;
+    @Mock
+    public RpcDefinition definition;
+    @Mock
+    public DOMRpcImplementation impl;
+    @Mock
+    public DOMRpcResult result;
+    public RoutedDOMRpcRoutingTableEntry entry;
 
     @Before
     public void before() {
-        doReturn(TestModel.TEST2_QNAME).when(rpcDefinition).getQName();
+        doReturn(Rpcs.BAR).when(definition).getQName();
         // Note: ImmutableMap.of() allows get(null), Map.of() does not
-        entry = new RoutedDOMRpcRoutingTableEntry(rpcDefinition, TestModel.TEST_PATH, ImmutableMap.of());
+        entry = new RoutedDOMRpcRoutingTableEntry(definition, CTX_IN_INPUT, ImmutableMap.of());
     }
 
     @Test
     public void testNewInstance() {
         final RoutedDOMRpcRoutingTableEntry instance = entry.newInstance(Map.of());
-        assertEquals(TestModel.TEST2_QNAME, entry.getType());
+        assertEquals(Rpcs.BAR, entry.getType());
         assertEquals(Map.of(), instance.getImplementations());
     }
 
     @Test
     public void testUnregistered()  {
-        final ListenableFuture<?> future = OperationInvocation.invoke(entry, TEST_CHILD);
-        final Throwable cause = assertThrows(ExecutionException.class, () -> Futures.getDone(future)).getCause();
+        assertRpcUnavailable(ONE_INPUT);
+        assertRpcUnavailable(TWO_INPUT);
+        assertRpcUnavailable(GLOBAL_INPUT);
+    }
+
+    @Test
+    public void testRegisteredGlobal() {
+        setPaths((YangInstanceIdentifier) null);
+        assertRpcAvailable(GLOBAL_INPUT);
+    }
+
+    @Test
+    public void testRegisteredGlobalOne() {
+        setPaths((YangInstanceIdentifier) null);
+        assertRpcAvailable(ONE_INPUT);
+    }
+
+    @Test
+    public void testRegisteredGlobalTwo() {
+        setPaths((YangInstanceIdentifier) null);
+        assertRpcAvailable(TWO_INPUT);
+    }
+
+    @Test
+    public void testRegisteredOne() {
+        setPaths(ONE_PATH);
+        assertRpcUnavailable(TWO_INPUT);
+        assertRpcAvailable(ONE_INPUT);
+    }
+
+    @Test
+    public void testRegisteredTwo() {
+        setPaths(TWO_PATH);
+        assertRpcUnavailable(ONE_INPUT);
+        assertRpcAvailable(TWO_INPUT);
+    }
+
+    @Test
+    public void testRemote() {
+        setPaths(YangInstanceIdentifier.empty());
+        assertRpcAvailable(ONE_INPUT);
+    }
+
+    @Test
+    public void testWrongContext() {
+        assertRpcUnavailable(Builders.containerBuilder()
+            .withNodeIdentifier(new NodeIdentifier(Rpcs.INPUT))
+            .withChild(ImmutableNodes.leafNode(Rpcs.CTX, "bad type"))
+            .build());
+    }
+
+    private void setPaths(final YangInstanceIdentifier... paths) {
+        final var map = new HashMap<YangInstanceIdentifier, List<DOMRpcImplementation>>();
+        for (var path : paths) {
+            map.put(path, List.of(impl));
+        }
+        entry = entry.newInstance(map);
+    }
+
+    private void assertRpcAvailable(final NormalizedNode input) {
+        doReturn(Futures.immediateFuture(result)).when(impl).invokeRpc(any(), any());
+
+        final var future = OperationInvocation.invoke(entry, input);
+        try {
+            assertSame(result, Futures.getDone(future));
+        } catch (ExecutionException e) {
+            throw new AssertionError(e);
+        }
+
+        verify(impl).invokeRpc(any(), any());
+    }
+
+    private void assertRpcUnavailable(final NormalizedNode input) {
+        final var future = OperationInvocation.invoke(entry, input);
+        final var cause = assertThrows(ExecutionException.class, () -> Futures.getDone(future)).getCause();
         assertThat(cause, instanceOf(DOMRpcImplementationNotAvailableException.class));
-        assertEquals("No implementation of RPC "
-            + "(urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test?revision=2014-03-13)test2 "
-            + "available",
-            cause.getMessage());
+        assertEquals("No implementation of RPC (rpcs)bar available", cause.getMessage());
     }
 }
index 094ccec4c1e5e42ecaadcce0a69d59d4fc588c5f..36e4ae260ac94df76ea5a19198879df3d63081cb 100644 (file)
@@ -8,15 +8,27 @@
 package org.opendaylight.mdsal.dom.broker;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.extension.yang.ext.rev130709.$YangModuleInfoImpl;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 
 @NonNullByDefault
 final class Rpcs {
-    static final EffectiveModelContext CONTEXT = YangParserTestUtils.parseYangResource("/rpcs.yang");
+    static final EffectiveModelContext CONTEXT = YangParserTestUtils.parseYangSources(YangParserConfiguration.DEFAULT,
+        null,
+        YangTextSchemaSource.delegateForByteSource("yang-ext.yang",
+            $YangModuleInfoImpl.getInstance().getYangTextByteSource()),
+        YangTextSchemaSource.forResource(Rpcs.class, "/rpcs.yang"));
+
     static final QName FOO = QName.create("rpcs", "foo");
     static final QName BAR = QName.create(FOO, "bar");
+    static final QName BAZ = QName.create(FOO, "baz");
+    static final QName NAME = QName.create(FOO, "name");
+    static final QName INPUT = QName.create(FOO, "input");
+    static final QName CTX = QName.create(FOO, "ctx");
 
     private Rpcs() {
         // Hidden on purpose
index 69439788c18609bc092786e81bc4b259a1462290..fc4b46d720213eb323fcea8e3e43d81c593f8a5b 100644 (file)
@@ -2,7 +2,29 @@ module rpcs {
   namespace rpcs;
   prefix rpcs;
 
+  import yang-ext {
+    prefix ext;
+  }
+
   rpc foo;
 
-  rpc bar;
+  identity context-type;
+
+  rpc bar {
+    input {
+      leaf ctx {
+        type instance-identifier;
+        ext:context-reference context-type;
+      }
+    }
+  }
+
+  list baz {
+    key name;
+    leaf name {
+      type string;
+    }
+
+    ext:context-instance context-type;
+  }
 }