2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.netconf.topology.singleton.impl;
10 import static java.nio.charset.StandardCharsets.UTF_8;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNull;
13 import static org.junit.Assert.assertTrue;
14 import static org.mockito.ArgumentMatchers.any;
15 import static org.mockito.ArgumentMatchers.anyCollection;
16 import static org.mockito.ArgumentMatchers.argThat;
17 import static org.mockito.ArgumentMatchers.eq;
18 import static org.mockito.Mockito.after;
19 import static org.mockito.Mockito.doAnswer;
20 import static org.mockito.Mockito.doNothing;
21 import static org.mockito.Mockito.doReturn;
22 import static org.mockito.Mockito.mock;
23 import static org.mockito.Mockito.reset;
24 import static org.mockito.Mockito.timeout;
25 import static org.mockito.Mockito.times;
26 import static org.mockito.Mockito.verify;
27 import static org.mockito.Mockito.verifyNoMoreInteractions;
28 import static org.mockito.MockitoAnnotations.initMocks;
30 import akka.actor.ActorRef;
31 import akka.actor.ActorSystem;
32 import akka.actor.Props;
33 import akka.actor.Status.Failure;
34 import akka.actor.Status.Success;
35 import akka.pattern.AskTimeoutException;
36 import akka.pattern.Patterns;
37 import akka.testkit.TestActorRef;
38 import akka.testkit.javadsl.TestKit;
39 import akka.util.Timeout;
40 import com.google.common.collect.ImmutableList;
41 import com.google.common.collect.Lists;
42 import com.google.common.io.ByteSource;
43 import com.google.common.net.InetAddresses;
44 import com.google.common.util.concurrent.Futures;
45 import com.google.common.util.concurrent.SettableFuture;
46 import java.io.InputStream;
47 import java.net.InetSocketAddress;
48 import java.util.ArrayList;
49 import java.util.Collections;
50 import java.util.List;
51 import java.util.Scanner;
52 import java.util.concurrent.ExecutionException;
53 import java.util.concurrent.TimeUnit;
54 import org.junit.After;
55 import org.junit.Before;
56 import org.junit.Rule;
57 import org.junit.Test;
58 import org.junit.rules.ExpectedException;
59 import org.mockito.ArgumentCaptor;
60 import org.mockito.Mock;
61 import org.opendaylight.controller.cluster.schema.provider.impl.YangTextSchemaSourceSerializationProxy;
62 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
63 import org.opendaylight.mdsal.dom.api.DOMActionException;
64 import org.opendaylight.mdsal.dom.api.DOMActionResult;
65 import org.opendaylight.mdsal.dom.api.DOMActionService;
66 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
67 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
68 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
69 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
70 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
71 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
72 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
73 import org.opendaylight.mdsal.dom.api.DOMNotificationService;
74 import org.opendaylight.mdsal.dom.api.DOMRpcException;
75 import org.opendaylight.mdsal.dom.api.DOMRpcResult;
76 import org.opendaylight.mdsal.dom.api.DOMRpcService;
77 import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
78 import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
79 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
80 import org.opendaylight.netconf.topology.singleton.impl.actors.NetconfNodeActor;
81 import org.opendaylight.netconf.topology.singleton.impl.utils.ClusteringActionException;
82 import org.opendaylight.netconf.topology.singleton.impl.utils.ClusteringRpcException;
83 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
84 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup.NetconfTopologySetupBuilder;
85 import org.opendaylight.netconf.topology.singleton.messages.AskForMasterMountPoint;
86 import org.opendaylight.netconf.topology.singleton.messages.CreateInitialMasterActorData;
87 import org.opendaylight.netconf.topology.singleton.messages.MasterActorDataInitialized;
88 import org.opendaylight.netconf.topology.singleton.messages.NotMasterException;
89 import org.opendaylight.netconf.topology.singleton.messages.RefreshSetupMasterActorData;
90 import org.opendaylight.netconf.topology.singleton.messages.RegisterMountPoint;
91 import org.opendaylight.netconf.topology.singleton.messages.UnregisterSlaveMountPoint;
92 import org.opendaylight.yangtools.concepts.ObjectRegistration;
93 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
94 import org.opendaylight.yangtools.yang.common.QName;
95 import org.opendaylight.yangtools.yang.common.RpcError;
96 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
97 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
98 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
99 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
100 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
101 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
102 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
103 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
104 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
105 import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
106 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
107 import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
108 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
109 import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
110 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
111 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
112 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
113 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
114 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
115 import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
116 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
117 import scala.concurrent.Await;
118 import scala.concurrent.Future;
119 import scala.concurrent.duration.Duration;
121 public class NetconfNodeActorTest {
123 private static final Timeout TIMEOUT = new Timeout(Duration.create(5, "seconds"));
124 private static final RevisionSourceIdentifier SOURCE_IDENTIFIER1 = RevisionSourceIdentifier.create("yang1");
125 private static final RevisionSourceIdentifier SOURCE_IDENTIFIER2 = RevisionSourceIdentifier.create("yang2");
127 private ActorSystem system = ActorSystem.create();
128 private final TestKit testKit = new TestKit(system);
131 public final ExpectedException exception = ExpectedException.none();
133 private ActorRef masterRef;
134 private RemoteDeviceId remoteDeviceId;
135 private final SharedSchemaRepository masterSchemaRepository = new SharedSchemaRepository("master");
138 private DOMRpcService mockDOMRpcService;
141 private DOMActionService mockDOMActionService;
144 private DOMMountPointService mockMountPointService;
147 private DOMMountPointService.DOMMountPointBuilder mockMountPointBuilder;
150 private ObjectRegistration<DOMMountPoint> mockMountPointReg;
153 private DOMDataBroker mockDOMDataBroker;
156 private SchemaSourceRegistration<?> mockSchemaSourceReg1;
159 private SchemaSourceRegistration<?> mockSchemaSourceReg2;
162 private SchemaSourceRegistry mockRegistry;
165 private EffectiveModelContextFactory mockSchemaContextFactory;
168 private SchemaRepository mockSchemaRepository;
171 private EffectiveModelContext mockSchemaContext;
174 public void setup() {
177 remoteDeviceId = new RemoteDeviceId("netconf-topology",
178 new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 9999));
180 masterSchemaRepository.registerSchemaSourceListener(
181 TextToASTTransformer.create(masterSchemaRepository, masterSchemaRepository));
183 final NetconfTopologySetup setup = NetconfTopologySetupBuilder.create().setActorSystem(system)
184 .setIdleTimeout(Duration.apply(1, TimeUnit.SECONDS)).build();
186 final Props props = NetconfNodeActor.props(setup, remoteDeviceId, masterSchemaRepository,
187 masterSchemaRepository, TIMEOUT, mockMountPointService);
189 masterRef = TestActorRef.create(system, props, "master_messages");
191 resetMountPointMocks();
193 doReturn(mockMountPointBuilder).when(mockMountPointService).createMountPoint(any());
195 doReturn(mockSchemaSourceReg1).when(mockRegistry).registerSchemaSource(any(), withSourceId(SOURCE_IDENTIFIER1));
196 doReturn(mockSchemaSourceReg2).when(mockRegistry).registerSchemaSource(any(), withSourceId(SOURCE_IDENTIFIER2));
198 doReturn(mockSchemaContextFactory).when(mockSchemaRepository)
199 .createEffectiveModelContextFactory();
203 public void teardown() {
204 TestKit.shutdownActorSystem(system, true);
209 public void testInitializeAndRefreshMasterData() {
211 // Test CreateInitialMasterActorData.
213 initializeMaster(new ArrayList<>());
215 // Test RefreshSetupMasterActorData.
217 final RemoteDeviceId newRemoteDeviceId = new RemoteDeviceId("netconf-topology2",
218 new InetSocketAddress(InetAddresses.forString("127.0.0.2"), 9999));
220 final NetconfTopologySetup newSetup = NetconfTopologySetupBuilder.create().setActorSystem(system).build();
222 masterRef.tell(new RefreshSetupMasterActorData(newSetup, newRemoteDeviceId), testKit.getRef());
224 testKit.expectMsgClass(MasterActorDataInitialized.class);
228 public void tesAskForMasterMountPoint() {
230 // Test with master not setup yet.
232 final TestKit kit = new TestKit(system);
234 masterRef.tell(new AskForMasterMountPoint(kit.getRef()), kit.getRef());
236 final Failure failure = kit.expectMsgClass(Failure.class);
237 assertTrue(failure.cause() instanceof NotMasterException);
239 // Now initialize - master should send the RegisterMountPoint message.
241 List<SourceIdentifier> sourceIdentifiers = Lists.newArrayList(RevisionSourceIdentifier.create("testID"));
242 initializeMaster(sourceIdentifiers);
244 masterRef.tell(new AskForMasterMountPoint(kit.getRef()), kit.getRef());
246 final RegisterMountPoint registerMountPoint = kit.expectMsgClass(RegisterMountPoint.class);
248 assertEquals(sourceIdentifiers, registerMountPoint.getSourceIndentifiers());
252 public void testRegisterAndUnregisterMountPoint() throws Exception {
254 ActorRef slaveRef = registerSlaveMountPoint();
258 slaveRef.tell(new UnregisterSlaveMountPoint(), testKit.getRef());
260 verify(mockMountPointReg, timeout(5000)).close();
261 verify(mockSchemaSourceReg1, timeout(1000)).close();
262 verify(mockSchemaSourceReg2, timeout(1000)).close();
264 // Test registration with another interleaved registration that completes while the first registration
265 // is resolving the schema context.
267 reset(mockSchemaSourceReg1, mockRegistry, mockSchemaRepository);
268 resetMountPointMocks();
270 doReturn(mockSchemaSourceReg1).when(mockRegistry).registerSchemaSource(any(), withSourceId(SOURCE_IDENTIFIER1));
272 doReturn(mockSchemaContextFactory).when(mockSchemaRepository)
273 .createEffectiveModelContextFactory();
275 final SchemaSourceRegistration<?> newMockSchemaSourceReg = mock(SchemaSourceRegistration.class);
277 final EffectiveModelContextFactory newMockSchemaContextFactory = mock(EffectiveModelContextFactory.class);
278 doReturn(Futures.immediateFuture(mockSchemaContext))
279 .when(newMockSchemaContextFactory).createEffectiveModelContext(anyCollection());
282 SettableFuture<SchemaContext> future = SettableFuture.create();
284 doReturn(newMockSchemaSourceReg).when(mockRegistry).registerSchemaSource(any(),
285 withSourceId(SOURCE_IDENTIFIER1));
287 doReturn(newMockSchemaContextFactory).when(mockSchemaRepository)
288 .createEffectiveModelContextFactory();
290 slaveRef.tell(new RegisterMountPoint(ImmutableList.of(SOURCE_IDENTIFIER1), masterRef),
293 future.set(mockSchemaContext);
296 }).when(mockSchemaContextFactory).createEffectiveModelContext(anyCollection());
298 doReturn(mockSchemaContextFactory).when(mockSchemaRepository)
299 .createEffectiveModelContextFactory();
301 slaveRef.tell(new RegisterMountPoint(ImmutableList.of(SOURCE_IDENTIFIER1), masterRef), testKit.getRef());
303 verify(mockMountPointBuilder, timeout(5000)).register();
304 verify(mockMountPointBuilder, after(500)).addInitialSchemaContext(mockSchemaContext);
305 verify(mockMountPointBuilder).addService(eq(DOMDataBroker.class), any());
306 verify(mockMountPointBuilder).addService(eq(DOMRpcService.class), any());
307 verify(mockMountPointBuilder).addService(eq(DOMActionService.class), any());
308 verify(mockMountPointBuilder).addService(eq(DOMNotificationService.class), any());
309 verify(mockSchemaSourceReg1).close();
310 verify(mockRegistry, times(2)).registerSchemaSource(any(), withSourceId(SOURCE_IDENTIFIER1));
311 verify(mockSchemaRepository, times(2)).createEffectiveModelContextFactory();
312 verifyNoMoreInteractions(mockMountPointBuilder, newMockSchemaSourceReg);
314 // Stop the slave actor and verify schema source registrations are closed.
316 final Future<Boolean> stopFuture = Patterns.gracefulStop(slaveRef, TIMEOUT.duration());
317 Await.result(stopFuture, TIMEOUT.duration());
319 verify(mockMountPointReg).close();
320 verify(newMockSchemaSourceReg).close();
323 @SuppressWarnings("unchecked")
325 public void testRegisterMountPointWithSchemaFailures() throws Exception {
326 final NetconfTopologySetup setup = NetconfTopologySetupBuilder.create().setActorSystem(system).build();
328 final ActorRef slaveRef = system.actorOf(NetconfNodeActor.props(setup, remoteDeviceId, mockRegistry,
329 mockSchemaRepository, TIMEOUT, mockMountPointService));
331 // Test unrecoverable failure.
333 doReturn(Futures.immediateFailedFuture(new SchemaResolutionException("mock")))
334 .when(mockSchemaContextFactory).createEffectiveModelContext(anyCollection());
336 slaveRef.tell(new RegisterMountPoint(ImmutableList.of(SOURCE_IDENTIFIER1, SOURCE_IDENTIFIER2),
337 masterRef), testKit.getRef());
339 testKit.expectMsgClass(Success.class);
341 verify(mockRegistry, timeout(5000)).registerSchemaSource(any(), withSourceId(SOURCE_IDENTIFIER1));
342 verify(mockRegistry, timeout(5000)).registerSchemaSource(any(), withSourceId(SOURCE_IDENTIFIER2));
344 verify(mockMountPointBuilder, after(1000).never()).register();
345 verify(mockSchemaSourceReg1, timeout(1000)).close();
346 verify(mockSchemaSourceReg2, timeout(1000)).close();
348 // Test recoverable AskTimeoutException - schema context resolution should be retried.
350 reset(mockSchemaSourceReg1, mockSchemaSourceReg2);
352 doReturn(Futures.immediateFailedFuture(new SchemaResolutionException("mock",
353 new AskTimeoutException("timeout"))))
354 .doReturn(Futures.immediateFuture(mockSchemaContext))
355 .when(mockSchemaContextFactory).createEffectiveModelContext(anyCollection());
357 slaveRef.tell(new RegisterMountPoint(ImmutableList.of(SOURCE_IDENTIFIER1, SOURCE_IDENTIFIER2),
358 masterRef), testKit.getRef());
360 testKit.expectMsgClass(Success.class);
362 verify(mockMountPointBuilder, timeout(5000)).register();
363 verifyNoMoreInteractions(mockSchemaSourceReg1, mockSchemaSourceReg2);
365 // Test AskTimeoutException with an interleaved successful registration. The first schema context resolution
366 // attempt should not be retried.
368 reset(mockSchemaSourceReg1, mockSchemaSourceReg2, mockSchemaRepository, mockSchemaContextFactory);
369 resetMountPointMocks();
371 final EffectiveModelContextFactory mockSchemaContextFactorySuccess = mock(EffectiveModelContextFactory.class);
372 doReturn(Futures.immediateFuture(mockSchemaContext))
373 .when(mockSchemaContextFactorySuccess).createEffectiveModelContext(anyCollection());
376 SettableFuture<SchemaContext> future = SettableFuture.create();
378 doReturn(mockSchemaContextFactorySuccess).when(mockSchemaRepository)
379 .createEffectiveModelContextFactory();
381 slaveRef.tell(new RegisterMountPoint(ImmutableList.of(SOURCE_IDENTIFIER1, SOURCE_IDENTIFIER2),
382 masterRef), testKit.getRef());
384 future.setException(new SchemaResolutionException("mock", new AskTimeoutException("timeout")));
387 }).when(mockSchemaContextFactory).createEffectiveModelContext(anyCollection());
389 doReturn(mockSchemaContextFactory).when(mockSchemaRepository).createEffectiveModelContextFactory();
391 slaveRef.tell(new RegisterMountPoint(ImmutableList.of(SOURCE_IDENTIFIER1, SOURCE_IDENTIFIER2),
392 masterRef), testKit.getRef());
394 verify(mockMountPointBuilder, timeout(5000)).register();
395 verify(mockSchemaRepository, times(2)).createEffectiveModelContextFactory();
399 public void testYangTextSchemaSourceRequest() throws Exception {
400 final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier.create("testID");
402 final ProxyYangTextSourceProvider proxyYangProvider =
403 new ProxyYangTextSourceProvider(masterRef, system.dispatcher(), TIMEOUT);
405 final YangTextSchemaSource yangTextSchemaSource = YangTextSchemaSource.delegateForByteSource(sourceIdentifier,
406 ByteSource.wrap("YANG".getBytes(UTF_8)));
410 final SchemaSourceRegistration<YangTextSchemaSource> schemaSourceReg = masterSchemaRepository
411 .registerSchemaSource(id -> Futures.immediateFuture(yangTextSchemaSource),
412 PotentialSchemaSource.create(sourceIdentifier, YangTextSchemaSource.class, 1));
414 final Future<YangTextSchemaSourceSerializationProxy> resolvedSchemaFuture =
415 proxyYangProvider.getYangTextSchemaSource(sourceIdentifier);
417 final YangTextSchemaSourceSerializationProxy success = Await.result(resolvedSchemaFuture, TIMEOUT.duration());
419 assertEquals(sourceIdentifier, success.getRepresentation().getIdentifier());
420 assertEquals("YANG", convertStreamToString(success.getRepresentation().openStream()));
422 // Test missing source failure.
424 exception.expect(MissingSchemaSourceException.class);
426 schemaSourceReg.close();
428 final Future<YangTextSchemaSourceSerializationProxy> failedSchemaFuture =
429 proxyYangProvider.getYangTextSchemaSource(sourceIdentifier);
431 Await.result(failedSchemaFuture, TIMEOUT.duration());
435 @SuppressWarnings({"checkstyle:AvoidHidingCauseException", "checkstyle:IllegalThrows"})
436 public void testSlaveInvokeRpc() throws Throwable {
438 final List<SourceIdentifier> sourceIdentifiers =
439 Lists.newArrayList(RevisionSourceIdentifier.create("testID"));
441 initializeMaster(sourceIdentifiers);
442 registerSlaveMountPoint();
444 ArgumentCaptor<DOMRpcService> domRPCServiceCaptor = ArgumentCaptor.forClass(DOMRpcService.class);
445 verify(mockMountPointBuilder).addService(eq(DOMRpcService.class), domRPCServiceCaptor.capture());
447 final DOMRpcService slaveDomRPCService = domRPCServiceCaptor.getValue();
448 assertTrue(slaveDomRPCService instanceof ProxyDOMRpcService);
450 final QName testQName = QName.create("", "TestQname");
451 final SchemaPath schemaPath = SchemaPath.create(true, testQName);
452 final NormalizedNode<?, ?> outputNode = ImmutableContainerNodeBuilder.create()
453 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(testQName))
454 .withChild(ImmutableNodes.leafNode(testQName, "foo")).build();
455 final RpcError rpcError = RpcResultBuilder.newError(RpcError.ErrorType.RPC, null, "Rpc invocation failed.");
457 // RPC with no response output.
459 doReturn(FluentFutures.immediateNullFluentFuture()).when(mockDOMRpcService).invokeRpc(any(), any());
461 DOMRpcResult result = slaveDomRPCService.invokeRpc(schemaPath, outputNode).get(2, TimeUnit.SECONDS);
463 assertEquals(null, result);
465 // RPC with response output.
467 doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult(outputNode)))
468 .when(mockDOMRpcService).invokeRpc(any(), any());
470 result = slaveDomRPCService.invokeRpc(schemaPath, outputNode).get(2, TimeUnit.SECONDS);
472 assertEquals(outputNode, result.getResult());
473 assertTrue(result.getErrors().isEmpty());
475 // RPC with response error.
477 doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult(rpcError)))
478 .when(mockDOMRpcService).invokeRpc(any(), any());
480 result = slaveDomRPCService.invokeRpc(schemaPath, outputNode).get(2, TimeUnit.SECONDS);
482 assertNull(result.getResult());
483 assertEquals(rpcError, result.getErrors().iterator().next());
485 // RPC with response output and error.
487 doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult(outputNode, rpcError)))
488 .when(mockDOMRpcService).invokeRpc(any(), any());
490 final DOMRpcResult resultOutputError =
491 slaveDomRPCService.invokeRpc(schemaPath, outputNode).get(2, TimeUnit.SECONDS);
493 assertEquals(outputNode, resultOutputError.getResult());
494 assertEquals(rpcError, resultOutputError.getErrors().iterator().next());
498 exception.expect(DOMRpcException.class);
500 doReturn(FluentFutures.immediateFailedFluentFuture(new ClusteringRpcException("mock")))
501 .when(mockDOMRpcService).invokeRpc(any(), any());
504 slaveDomRPCService.invokeRpc(schemaPath, outputNode).get(2, TimeUnit.SECONDS);
505 } catch (ExecutionException e) {
511 @SuppressWarnings({"checkstyle:AvoidHidingCauseException", "checkstyle:IllegalThrows"})
512 public void testSlaveInvokeAction() throws Throwable {
513 final List<SourceIdentifier> sourceIdentifiers = Lists
514 .newArrayList(RevisionSourceIdentifier.create("testActionID"));
515 initializeMaster(sourceIdentifiers);
516 registerSlaveMountPoint();
518 ArgumentCaptor<DOMActionService> domActionServiceCaptor = ArgumentCaptor.forClass(DOMActionService.class);
519 verify(mockMountPointBuilder).addService(eq(DOMActionService.class), domActionServiceCaptor.capture());
521 final DOMActionService slaveDomActionService = domActionServiceCaptor.getValue();
522 assertTrue(slaveDomActionService instanceof ProxyDOMActionService);
524 final QName testQName = QName.create("test", "2019-08-16", "TestActionQname");
525 final SchemaPath schemaPath = SchemaPath.create(true, testQName);
527 final YangInstanceIdentifier yangIIdPath = YangInstanceIdentifier
528 .create(new YangInstanceIdentifier.NodeIdentifier(testQName));
530 final DOMDataTreeIdentifier domDataTreeIdentifier = new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL,
533 final ContainerNode outputNode = ImmutableContainerNodeBuilder.create()
534 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(testQName))
535 .withChild(ImmutableNodes.leafNode(testQName, "foo")).build();
537 // Action with no response output.
538 doReturn(FluentFutures.immediateNullFluentFuture()).when(mockDOMActionService)
539 .invokeAction(any(), any(), any());
540 DOMActionResult result = slaveDomActionService.invokeAction(schemaPath, domDataTreeIdentifier, outputNode)
541 .get(2, TimeUnit.SECONDS);
542 assertEquals(null, result);
544 // Action with response output.
545 doReturn(FluentFutures.immediateFluentFuture(new SimpleDOMActionResult(outputNode))).when(mockDOMActionService)
546 .invokeAction(any(), any(), any());
547 result = slaveDomActionService.invokeAction(schemaPath, domDataTreeIdentifier, outputNode)
548 .get(2, TimeUnit.SECONDS);
550 assertEquals(outputNode, result.getOutput().get());
551 assertTrue(result.getErrors().isEmpty());
554 exception.expect(DOMActionException.class);
555 doReturn(FluentFutures.immediateFailedFluentFuture(new ClusteringActionException("mock")))
556 .when(mockDOMActionService).invokeAction(any(), any(), any());
558 slaveDomActionService.invokeAction(schemaPath, domDataTreeIdentifier, outputNode).get(2, TimeUnit.SECONDS);
559 } catch (ExecutionException e) {
565 public void testSlaveNewTransactionRequests() {
567 doReturn(mock(DOMDataTreeReadTransaction.class)).when(mockDOMDataBroker).newReadOnlyTransaction();
568 doReturn(mock(DOMDataTreeReadWriteTransaction.class)).when(mockDOMDataBroker).newReadWriteTransaction();
569 doReturn(mock(DOMDataTreeWriteTransaction.class)).when(mockDOMDataBroker).newWriteOnlyTransaction();
571 initializeMaster(Collections.emptyList());
572 registerSlaveMountPoint();
574 ArgumentCaptor<DOMDataBroker> domDataBrokerCaptor = ArgumentCaptor.forClass(DOMDataBroker.class);
575 verify(mockMountPointBuilder).addService(eq(DOMDataBroker.class), domDataBrokerCaptor.capture());
577 final DOMDataBroker slaveDOMDataBroker = domDataBrokerCaptor.getValue();
578 assertTrue(slaveDOMDataBroker instanceof ProxyDOMDataBroker);
580 slaveDOMDataBroker.newReadOnlyTransaction();
581 verify(mockDOMDataBroker).newReadOnlyTransaction();
583 slaveDOMDataBroker.newReadWriteTransaction();
584 verify(mockDOMDataBroker).newReadWriteTransaction();
586 slaveDOMDataBroker.newWriteOnlyTransaction();
587 verify(mockDOMDataBroker).newWriteOnlyTransaction();
590 private ActorRef registerSlaveMountPoint() {
591 final ActorRef slaveRef = system.actorOf(NetconfNodeActor.props(
592 NetconfTopologySetupBuilder.create().setActorSystem(system).build(), remoteDeviceId, mockRegistry,
593 mockSchemaRepository, TIMEOUT, mockMountPointService));
595 doReturn(Futures.immediateFuture(mockSchemaContext))
596 .when(mockSchemaContextFactory).createEffectiveModelContext(anyCollection());
598 slaveRef.tell(new RegisterMountPoint(ImmutableList.of(SOURCE_IDENTIFIER1, SOURCE_IDENTIFIER2),
599 masterRef), testKit.getRef());
601 verify(mockMountPointBuilder, timeout(5000)).register();
602 verify(mockMountPointBuilder).addInitialSchemaContext(mockSchemaContext);
603 verify(mockMountPointBuilder).addService(eq(DOMDataBroker.class), any());
604 verify(mockMountPointBuilder).addService(eq(DOMRpcService.class), any());
605 verify(mockMountPointBuilder).addService(eq(DOMNotificationService.class), any());
607 testKit.expectMsgClass(Success.class);
612 private void initializeMaster(final List<SourceIdentifier> sourceIdentifiers) {
613 masterRef.tell(new CreateInitialMasterActorData(mockDOMDataBroker, sourceIdentifiers,
614 mockDOMRpcService, mockDOMActionService), testKit.getRef());
616 testKit.expectMsgClass(MasterActorDataInitialized.class);
619 private void resetMountPointMocks() {
620 reset(mockMountPointReg, mockMountPointBuilder);
622 doNothing().when(mockMountPointReg).close();
624 doReturn(mockMountPointBuilder).when(mockMountPointBuilder).addInitialSchemaContext(any());
625 doReturn(mockMountPointBuilder).when(mockMountPointBuilder).addService(any(), any());
626 doReturn(mockMountPointReg).when(mockMountPointBuilder).register();
629 private static PotentialSchemaSource<?> withSourceId(final SourceIdentifier identifier) {
630 return argThat(argument -> identifier.equals(argument.getSourceIdentifier()));
633 private static String convertStreamToString(final InputStream is) {
634 try (Scanner scanner = new Scanner(is)) {
635 return scanner.useDelimiter("\\A").hasNext() ? scanner.next() : "";