Improve DOMRpcRouterTest
[mdsal.git] / dom / mdsal-dom-broker / src / test / java / org / opendaylight / mdsal / dom / broker / DOMRpcRouterTest.java
1 /*
2  * Copyright (c) 2016, 2017 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.dom.broker;
9
10 import static org.hamcrest.CoreMatchers.instanceOf;
11 import static org.hamcrest.MatcherAssert.assertThat;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertFalse;
14 import static org.junit.Assert.assertNotEquals;
15 import static org.junit.Assert.assertNotNull;
16 import static org.junit.Assert.assertThrows;
17 import static org.junit.Assert.assertTrue;
18 import static org.mockito.Mockito.mock;
19
20 import com.google.common.util.concurrent.Futures;
21 import com.google.common.util.concurrent.ListenableFuture;
22 import java.util.Collection;
23 import java.util.List;
24 import java.util.concurrent.ExecutionException;
25 import java.util.concurrent.RejectedExecutionException;
26 import org.junit.BeforeClass;
27 import org.junit.Test;
28 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
29 import org.opendaylight.mdsal.dom.api.DOMActionImplementation;
30 import org.opendaylight.mdsal.dom.api.DOMActionInstance;
31 import org.opendaylight.mdsal.dom.api.DOMActionNotAvailableException;
32 import org.opendaylight.mdsal.dom.api.DOMActionProviderService;
33 import org.opendaylight.mdsal.dom.api.DOMActionResult;
34 import org.opendaylight.mdsal.dom.api.DOMActionService;
35 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
36 import org.opendaylight.mdsal.dom.api.DOMRpcAvailabilityListener;
37 import org.opendaylight.mdsal.dom.api.DOMRpcIdentifier;
38 import org.opendaylight.mdsal.dom.api.DOMRpcProviderService;
39 import org.opendaylight.mdsal.dom.broker.util.TestModel;
40 import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
41 import org.opendaylight.yangtools.concepts.ObjectRegistration;
42 import org.opendaylight.yangtools.yang.common.QName;
43 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
44 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
45 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
46 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
47 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
48 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
49 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
50
51 public class DOMRpcRouterTest extends TestUtils {
52     private static final QName FOO = QName.create("actions", "foo");
53     private static final QName BAR = QName.create(FOO, "bar");
54     private static final QName BAZ = QName.create(FOO, "baz");
55     private static final QName INPUT = QName.create(FOO, "input");
56     private static final QName OUTPUT = QName.create(FOO, "output");
57
58     private static final Absolute BAZ_TYPE = Absolute.of(FOO, BAZ);
59     private static final YangInstanceIdentifier BAZ_PATH_BAD = YangInstanceIdentifier.create(
60         new NodeIdentifier(FOO), NodeIdentifierWithPredicates.of(FOO, BAR, "bad"));
61     private static final YangInstanceIdentifier BAZ_PATH_GOOD = YangInstanceIdentifier.create(
62         new NodeIdentifier(FOO), NodeIdentifierWithPredicates.of(FOO, BAR, "good"));
63
64     private static final DOMActionImplementation IMPL =
65         (type, path, input) -> Futures.immediateFuture(new SimpleDOMActionResult(
66             Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(OUTPUT)).build()));
67
68     private static EffectiveModelContext ACTIONS_CONTEXT;
69
70     @BeforeClass
71     public static void beforeClass() {
72         ACTIONS_CONTEXT = YangParserTestUtils.parseYangResource("/actions.yang");
73     }
74
75     @Test
76     public void registerRpcImplementation() {
77         try (DOMRpcRouter rpcRouter = new DOMRpcRouter()) {
78             DOMRpcRoutingTable routingTable = rpcRouter.routingTable();
79             assertFalse(routingTable.getOperations().containsKey(TestModel.TEST_QNAME));
80
81             rpcRouter.getRpcProviderService().registerRpcImplementation(getTestRpcImplementation(),
82                 DOMRpcIdentifier.create(TestModel.TEST_QNAME, null));
83             routingTable = rpcRouter.routingTable();
84             assertTrue(routingTable.getOperations().containsKey(TestModel.TEST_QNAME));
85
86             rpcRouter.getRpcProviderService().registerRpcImplementation(getTestRpcImplementation(),
87                 DOMRpcIdentifier.create(TestModel.TEST2_QNAME, null));
88             routingTable = rpcRouter.routingTable();
89             assertTrue(routingTable.getOperations().containsKey(TestModel.TEST2_QNAME));
90         }
91     }
92
93     @Test
94     public void invokeRpc() {
95         try (DOMRpcRouter rpcRouter = new DOMRpcRouter()) {
96             assertNotNull(rpcRouter.getRpcService().invokeRpc(TestModel.TEST_QNAME, null));
97         }
98     }
99
100     @Test
101     public void registerRpcListener() {
102         try (DOMRpcRouter rpcRouter = new DOMRpcRouter()) {
103             final DOMRpcAvailabilityListener listener = mock(DOMRpcAvailabilityListener.class);
104
105             final Collection<?> listenersOriginal = rpcRouter.listeners();
106
107             assertNotNull(rpcRouter.getRpcService().registerRpcListener(listener));
108
109             final Collection<?> listenersChanged = rpcRouter.listeners();
110             assertNotEquals(listenersOriginal, listenersChanged);
111             assertTrue(listenersOriginal.isEmpty());
112             assertFalse(listenersChanged.isEmpty());
113         }
114     }
115
116     @Test
117     public void onGlobalContextUpdated() {
118         try (DOMRpcRouter rpcRouter = new DOMRpcRouter()) {
119
120             final DOMRpcRoutingTable routingTableOriginal = rpcRouter.routingTable();
121
122             rpcRouter.onModelContextUpdated(TestModel.createTestContext());
123
124             final DOMRpcRoutingTable routingTableChanged = rpcRouter.routingTable();
125             assertNotEquals(routingTableOriginal, routingTableChanged);
126         }
127     }
128
129     @Test
130     public void close() {
131         final DOMRpcRouter rpcRouter = new DOMRpcRouter();
132         rpcRouter.close();
133
134         final DOMRpcProviderService svc = rpcRouter.getRpcProviderService();
135         assertThrows(RejectedExecutionException.class, () -> svc.registerRpcImplementation(getTestRpcImplementation(),
136             DOMRpcIdentifier.create(TestModel.TEST_QNAME, null)));
137     }
138
139     @Test
140     public void testActionInstanceRouting() throws ExecutionException {
141         try (DOMRpcRouter rpcRouter = new DOMRpcRouter()) {
142             rpcRouter.onModelContextUpdated(ACTIONS_CONTEXT);
143
144             final DOMActionProviderService actionProvider = rpcRouter.getActionProviderService();
145             assertNotNull(actionProvider);
146             final DOMActionService actionConsumer = rpcRouter.getActionService();
147             assertNotNull(actionConsumer);
148
149             try (ObjectRegistration<?> reg = actionProvider.registerActionImplementation(IMPL,
150                 DOMActionInstance.of(BAZ_TYPE, LogicalDatastoreType.OPERATIONAL, BAZ_PATH_GOOD))) {
151
152                 assertAvailable(actionConsumer, BAZ_PATH_GOOD);
153                 assertUnavailable(actionConsumer, BAZ_PATH_BAD);
154             }
155
156             assertUnavailable(actionConsumer, BAZ_PATH_BAD);
157             assertUnavailable(actionConsumer, BAZ_PATH_GOOD);
158         }
159     }
160
161     private static void assertAvailable(final DOMActionService actionService, final YangInstanceIdentifier path) {
162         final DOMActionResult result;
163         try {
164             result = Futures.getDone(invokeBaz(actionService, path));
165         } catch (ExecutionException e) {
166             throw new AssertionError("Unexpected invocation failure", e);
167         }
168         assertEquals(List.of(), result.getErrors());
169     }
170
171     private static void assertUnavailable(final DOMActionService actionService, final YangInstanceIdentifier path) {
172         final ListenableFuture<? extends DOMActionResult> future = invokeBaz(actionService, path);
173         final ExecutionException ex = assertThrows(ExecutionException.class, () -> Futures.getDone(future));
174         assertThat(ex.getCause(), instanceOf(DOMActionNotAvailableException.class));
175     }
176
177     private static ListenableFuture<? extends DOMActionResult> invokeBaz(final DOMActionService actionService,
178             final YangInstanceIdentifier path) {
179         return actionService.invokeAction(BAZ_TYPE, new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, path),
180             Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(INPUT)).build());
181     }
182 }