2 * Copyright (c) 2014, 2015 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.client.mdsal;
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.assertTrue;
15 import static org.mockito.ArgumentMatchers.any;
16 import static org.mockito.ArgumentMatchers.anyCollection;
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.spy;
24 import static org.mockito.Mockito.timeout;
25 import static org.mockito.Mockito.times;
26 import static org.mockito.Mockito.verify;
28 import com.google.common.util.concurrent.Futures;
29 import com.google.common.util.concurrent.MoreExecutors;
30 import com.google.common.util.concurrent.SettableFuture;
31 import java.net.InetSocketAddress;
32 import java.util.ArrayList;
33 import java.util.Collection;
34 import java.util.HashMap;
35 import java.util.List;
38 import org.junit.BeforeClass;
39 import org.junit.Test;
40 import org.junit.runner.RunWith;
41 import org.mockito.ArgumentCaptor;
42 import org.mockito.Mock;
43 import org.mockito.junit.MockitoJUnitRunner;
44 import org.opendaylight.mdsal.dom.api.DOMNotification;
45 import org.opendaylight.netconf.api.CapabilityURN;
46 import org.opendaylight.netconf.api.messages.NetconfMessage;
47 import org.opendaylight.netconf.api.xml.XmlUtil;
48 import org.opendaylight.netconf.client.mdsal.NetconfDevice.EmptySchemaContextException;
49 import org.opendaylight.netconf.client.mdsal.api.NetconfDeviceSchemasResolver;
50 import org.opendaylight.netconf.client.mdsal.api.NetconfSessionPreferences;
51 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceHandler;
52 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
53 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.connection.oper.available.capabilities.AvailableCapability;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.connection.oper.available.capabilities.AvailableCapability.CapabilityOrigin;
57 import org.opendaylight.yangtools.concepts.Registration;
58 import org.opendaylight.yangtools.yang.common.QName;
59 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
60 import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
61 import org.opendaylight.yangtools.yang.model.api.source.YangTextSource;
62 import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
63 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
64 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
65 import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
66 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
68 @RunWith(MockitoJUnitRunner.StrictStubs.class)
69 public class NetconfDeviceTest extends AbstractTestModelTest {
70 public static final String TEST_NAMESPACE = "test:namespace";
71 public static final String TEST_MODULE = "test-module";
72 public static final String TEST_REVISION = "2013-07-22";
73 public static final SourceIdentifier TEST_SID = new SourceIdentifier(TEST_MODULE, TEST_REVISION);
74 public static final String TEST_CAPABILITY =
75 TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION;
77 public static final SourceIdentifier TEST_SID2 = new SourceIdentifier(TEST_MODULE + "2", TEST_REVISION);
78 public static final String TEST_CAPABILITY2 =
79 TEST_NAMESPACE + "?module=" + TEST_MODULE + "2" + "&revision=" + TEST_REVISION;
81 private static final NetconfDeviceSchemasResolver STATE_SCHEMAS_RESOLVER =
82 (deviceRpc, remoteSessionCapabilities, id, schemaContext) -> Futures.immediateFuture(NetconfStateSchemas.EMPTY);
84 private static NetconfMessage NOTIFICATION;
87 private SchemaSourceRegistry schemaRegistry;
90 public static final void setupNotification() throws Exception {
91 NOTIFICATION = new NetconfMessage(XmlUtil.readXmlToDocument(
92 NetconfDeviceTest.class.getResourceAsStream("/notification-payload.xml")));
96 public void testNetconfDeviceFlawedModelFailedResolution() throws Exception {
97 final RemoteDeviceHandler facade = getFacade();
98 final NetconfDeviceCommunicator listener = getListener();
100 final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
101 final SchemaRepository schemaRepository = getSchemaRepository();
103 final SchemaResolutionException schemaResolutionException =
104 new SchemaResolutionException("fail first", TEST_SID, new Throwable("YangTools parser fail"));
105 doAnswer(invocation -> {
106 if (invocation.getArgument(0, Collection.class).size() == 2) {
107 return Futures.immediateFailedFuture(schemaResolutionException);
109 return Futures.immediateFuture(SCHEMA_CONTEXT);
111 }).when(schemaFactory).createEffectiveModelContext(anyCollection());
113 final NetconfDeviceSchemasResolver stateSchemasResolver =
114 (deviceRpc, remoteSessionCapabilities, id, schemaContext) -> {
115 final var first = SCHEMA_CONTEXT.getModules().iterator().next();
116 final var qName = QName.create(first.getQNameModule(), first.getName());
117 return Futures.immediateFuture(new NetconfStateSchemas(
118 Set.of(qName, QName.create(first.getQNameModule(), "test-module2"))));
121 doReturn(mock(Registration.class)).when(schemaRegistry).registerSchemaSource(any(), any());
122 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
123 .SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaFactory, stateSchemasResolver);
125 final NetconfDevice device = new NetconfDeviceBuilder()
126 .setReconnectOnSchemasChange(true)
127 .setSchemaResourcesDTO(schemaResourcesDTO)
128 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
130 .setSalFacade(facade)
131 .setBaseSchemas(BASE_SCHEMAS)
133 // Monitoring supported
134 final NetconfSessionPreferences sessionCaps = getSessionCaps(true, List.of(TEST_CAPABILITY, TEST_CAPABILITY2));
135 device.onRemoteSessionUp(sessionCaps, listener);
137 verify(facade, timeout(5000)).onDeviceConnected(any(NetconfDeviceSchema.class),
138 any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
139 verify(schemaFactory, times(2)).createEffectiveModelContext(anyCollection());
143 public void testNetconfDeviceFailFirstSchemaFailSecondEmpty() throws Exception {
144 final RemoteDeviceHandler facade = getFacade();
145 final NetconfDeviceCommunicator listener = getListener();
147 final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
148 final SchemaRepository schemaRepository = getSchemaRepository();
150 // Make fallback attempt to fail due to empty resolved sources
151 final SchemaResolutionException schemaResolutionException = new SchemaResolutionException("fail first",
152 new SourceIdentifier("test-module", "2013-07-22"), new Throwable());
153 doReturn(Futures.immediateFailedFuture(schemaResolutionException))
154 .when(schemaFactory).createEffectiveModelContext(anyCollection());
156 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
157 .SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaFactory, STATE_SCHEMAS_RESOLVER);
158 final NetconfDevice device = new NetconfDeviceBuilder()
159 .setReconnectOnSchemasChange(true)
160 .setSchemaResourcesDTO(schemaResourcesDTO)
161 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
163 .setSalFacade(facade)
164 .setBaseSchemas(BASE_SCHEMAS)
167 // Monitoring not supported
168 final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of(TEST_CAPABILITY));
169 device.onRemoteSessionUp(sessionCaps, listener);
171 final var captor = ArgumentCaptor.forClass(Throwable.class);
172 verify(facade, timeout(5000)).onDeviceFailed(captor.capture());
173 assertThat(captor.getValue(), instanceOf(EmptySchemaContextException.class));
175 verify(listener, timeout(5000)).close();
176 verify(schemaFactory, times(1)).createEffectiveModelContext(anyCollection());
180 public void testNetconfDeviceMissingSource() throws Exception {
181 final RemoteDeviceHandler facade = getFacade();
182 final NetconfDeviceCommunicator listener = getListener();
184 final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
185 final SchemaRepository schemaRepository = getSchemaRepository();
187 // Make fallback attempt to fail due to empty resolved sources
188 final MissingSchemaSourceException schemaResolutionException =
189 new MissingSchemaSourceException(TEST_SID, "fail first");
190 doReturn(Futures.immediateFailedFuture(schemaResolutionException))
191 .when(schemaRepository).getSchemaSource(eq(TEST_SID), eq(YangTextSource.class));
192 doAnswer(invocation -> {
193 if (invocation.getArgument(0, Collection.class).size() == 2) {
194 return Futures.immediateFailedFuture(schemaResolutionException);
196 return Futures.immediateFuture(SCHEMA_CONTEXT);
198 }).when(schemaFactory).createEffectiveModelContext(anyCollection());
200 final NetconfDeviceSchemasResolver stateSchemasResolver =
201 (deviceRpc, remoteSessionCapabilities, id, schemaContext) -> {
202 final var first = SCHEMA_CONTEXT.getModules().iterator().next();
203 final var qName = QName.create(first.getQNameModule(), first.getName());
204 return Futures.immediateFuture(new NetconfStateSchemas(
205 Set.of(qName, QName.create(first.getQNameModule(), "test-module2"))));
208 doReturn(mock(Registration.class)).when(schemaRegistry).registerSchemaSource(any(), any());
209 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
210 .SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaFactory, stateSchemasResolver);
212 final NetconfDevice device = new NetconfDeviceBuilder()
213 .setReconnectOnSchemasChange(true)
214 .setSchemaResourcesDTO(schemaResourcesDTO)
215 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
216 .setBaseSchemas(BASE_SCHEMAS)
218 .setSalFacade(facade)
220 // Monitoring supported
221 final NetconfSessionPreferences sessionCaps =
222 getSessionCaps(true, List.of(TEST_CAPABILITY, TEST_CAPABILITY2));
223 device.onRemoteSessionUp(sessionCaps, listener);
225 verify(facade, timeout(5000)).onDeviceConnected(any(NetconfDeviceSchema.class),
226 any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
227 verify(schemaFactory, times(1)).createEffectiveModelContext(anyCollection());
230 private static SchemaRepository getSchemaRepository() {
231 final SchemaRepository mock = mock(SchemaRepository.class);
232 final YangTextSource mockRep = mock(YangTextSource.class);
233 doReturn(Futures.immediateFuture(mockRep))
234 .when(mock).getSchemaSource(any(SourceIdentifier.class), eq(YangTextSource.class));
239 public void testNotificationBeforeSchema() throws Exception {
240 final RemoteDeviceHandler facade = getFacade();
241 final NetconfDeviceCommunicator listener = getListener();
242 final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
243 final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
244 doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
245 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
246 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
247 final NetconfDevice device = new NetconfDeviceBuilder()
248 .setReconnectOnSchemasChange(true)
249 .setSchemaResourcesDTO(schemaResourcesDTO)
250 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
252 .setSalFacade(facade)
253 .setBaseSchemas(BASE_SCHEMAS)
256 final NetconfSessionPreferences sessionCaps = getSessionCaps(true, List.of(TEST_CAPABILITY));
257 device.onRemoteSessionUp(sessionCaps, listener);
259 device.onNotification(NOTIFICATION);
260 device.onNotification(NOTIFICATION);
261 verify(facade, times(0)).onNotification(any(DOMNotification.class));
263 verify(facade, times(0)).onNotification(any(DOMNotification.class));
264 schemaFuture.set(NetconfToNotificationTest.getNotificationSchemaContext(getClass(), false));
265 verify(facade, timeout(10000).times(2)).onNotification(any(DOMNotification.class));
267 device.onNotification(NOTIFICATION);
268 verify(facade, timeout(10000).times(3)).onNotification(any(DOMNotification.class));
272 public void testNetconfDeviceReconnect() throws Exception {
273 final RemoteDeviceHandler facade = getFacade();
274 final NetconfDeviceCommunicator listener = getListener();
276 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
278 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
279 schemaRegistry, getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
280 final NetconfDevice device = new NetconfDeviceBuilder()
281 .setReconnectOnSchemasChange(true)
282 .setSchemaResourcesDTO(schemaResourcesDTO)
283 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
285 .setSalFacade(facade)
286 .setBaseSchemas(BASE_SCHEMAS)
288 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
289 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
290 device.onRemoteSessionUp(sessionCaps, listener);
292 verify(schemaContextProviderFactory, timeout(5000)).createEffectiveModelContext(anyCollection());
293 verify(facade, timeout(5000)).onDeviceConnected(
294 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
296 device.onRemoteSessionDown();
297 verify(facade, timeout(5000)).onDeviceDisconnected();
299 device.onRemoteSessionUp(sessionCaps, listener);
301 verify(schemaContextProviderFactory, timeout(5000).times(2)).createEffectiveModelContext(anyCollection());
302 verify(facade, timeout(5000).times(2)).onDeviceConnected(
303 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
307 public void testNetconfDeviceDisconnectListenerCallCancellation() throws Exception {
308 final RemoteDeviceHandler facade = getFacade();
309 final NetconfDeviceCommunicator listener = getListener();
310 final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
311 final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
312 doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
313 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
314 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
315 final NetconfDevice device = new NetconfDeviceBuilder()
316 .setReconnectOnSchemasChange(true)
317 .setSchemaResourcesDTO(schemaResourcesDTO)
318 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
320 .setSalFacade(facade)
321 .setBaseSchemas(BASE_SCHEMAS)
323 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
324 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
325 //session up, start schema resolution
326 device.onRemoteSessionUp(sessionCaps, listener);
328 device.onRemoteSessionDown();
329 verify(facade, timeout(5000)).onDeviceDisconnected();
330 //complete schema setup
331 schemaFuture.set(SCHEMA_CONTEXT);
332 //facade.onDeviceDisconnected() was called, so facade.onDeviceConnected() shouldn't be called anymore
333 verify(facade, after(1000).never()).onDeviceConnected(any(), any(), any(RemoteDeviceServices.class));
337 public void testNetconfDeviceReconnectBeforeSchemaSetup() throws Exception {
338 final RemoteDeviceHandler facade = getFacade();
340 final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
341 final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
342 doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
344 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
345 schemaRegistry, getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
346 final NetconfDevice device = new NetconfDeviceBuilder()
347 .setReconnectOnSchemasChange(true)
348 .setSchemaResourcesDTO(schemaResourcesDTO)
349 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
351 .setSalFacade(facade)
352 .setBaseSchemas(BASE_SCHEMAS)
354 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
355 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
357 final NetconfDeviceCommunicator listener = getListener();
358 // session up, start schema resolution
359 device.onRemoteSessionUp(sessionCaps, listener);
361 device.onRemoteSessionDown();
362 verify(facade, timeout(5000)).onDeviceDisconnected();
363 // session back up, start another schema resolution
364 device.onRemoteSessionUp(sessionCaps, listener);
365 // complete schema setup
366 schemaFuture.set(SCHEMA_CONTEXT);
367 // schema setup performed twice
368 verify(schemaContextProviderFactory, timeout(5000).times(2)).createEffectiveModelContext(anyCollection());
369 // onDeviceConnected called once
370 verify(facade, timeout(5000)).onDeviceConnected(
371 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
375 public void testNetconfDeviceAvailableCapabilitiesBuilding() throws Exception {
376 final RemoteDeviceHandler facade = getFacade();
377 final NetconfDeviceCommunicator listener = getListener();
379 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
381 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
382 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
383 final NetconfDevice device = new NetconfDeviceBuilder()
384 .setReconnectOnSchemasChange(true)
385 .setSchemaResourcesDTO(schemaResourcesDTO)
386 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
388 .setSalFacade(facade)
389 .setBaseSchemas(BASE_SCHEMAS)
391 final NetconfDevice netconfSpy = spy(device);
393 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
394 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
395 final Map<QName, CapabilityOrigin> moduleBasedCaps = new HashMap<>();
396 moduleBasedCaps.putAll(sessionCaps.moduleBasedCaps());
398 .put(QName.create("(test:qname:side:loading)test"), CapabilityOrigin.UserDefined);
400 netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), listener);
402 final var argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
403 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
404 any(RemoteDeviceServices.class));
405 argument.getValue().capabilities().resolvedCapabilities()
406 .forEach(entry -> assertEquals("Builded 'AvailableCapability' schemas should match input capabilities.",
408 QName.create(entry.getCapability())).getName(), entry.getCapabilityOrigin().getName()));
412 public void testNetconfDeviceNotificationsModelNotPresentWithCapability() throws Exception {
413 final RemoteDeviceHandler facade = getFacade();
414 final NetconfDeviceCommunicator listener = getListener();
415 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
417 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
418 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
419 final NetconfDevice device = new NetconfDeviceBuilder()
420 .setSchemaResourcesDTO(schemaResourcesDTO)
421 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
423 .setSalFacade(facade)
424 .setBaseSchemas(BASE_SCHEMAS)
426 final NetconfDevice netconfSpy = spy(device);
428 final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of(CapabilityURN.NOTIFICATION));
430 netconfSpy.onRemoteSessionUp(sessionCaps, listener);
432 final var argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
433 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
434 any(RemoteDeviceServices.class));
436 List<String> notificationModulesName = List.of(
437 org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
438 .YangModuleInfoImpl.getInstance().getName().toString(),
439 org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
440 .YangModuleInfoImpl.getInstance().getName().toString());
442 final Set<AvailableCapability> resolvedCapabilities = argument.getValue().capabilities().resolvedCapabilities();
444 assertEquals(2, resolvedCapabilities.size());
445 assertTrue(resolvedCapabilities.stream().anyMatch(entry -> notificationModulesName
446 .contains(entry.getCapability())));
450 public void testNetconfDeviceNotificationsCapabilityIsNotPresent() throws Exception {
451 final RemoteDeviceHandler facade = getFacade();
452 final NetconfDeviceCommunicator listener = getListener();
453 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
455 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
456 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
457 final NetconfDevice device = new NetconfDeviceBuilder()
458 .setSchemaResourcesDTO(schemaResourcesDTO)
459 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
461 .setSalFacade(facade)
462 .setBaseSchemas(BASE_SCHEMAS)
464 final NetconfDevice netconfSpy = spy(device);
466 final NetconfSessionPreferences sessionCaps = getSessionCaps(false,
467 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
469 netconfSpy.onRemoteSessionUp(sessionCaps, listener);
471 final var argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
472 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
473 any(RemoteDeviceServices.class));
474 final NetconfDeviceCapabilities netconfDeviceCaps = argument.getValue().capabilities();
476 List<String> notificationModulesName = List.of(
477 org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
478 .YangModuleInfoImpl.getInstance().getName().toString(),
479 org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
480 .YangModuleInfoImpl.getInstance().getName().toString());
482 assertFalse(netconfDeviceCaps.resolvedCapabilities().stream()
483 .anyMatch(entry -> notificationModulesName.contains(entry.getCapability())));
487 public void testNetconfDeviceNotificationsModelIsPresent() throws Exception {
488 final RemoteDeviceHandler facade = getFacade();
489 final NetconfDeviceCommunicator listener = getListener();
490 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
492 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
493 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
494 final NetconfDevice device = new NetconfDeviceBuilder()
495 .setSchemaResourcesDTO(schemaResourcesDTO)
496 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
498 .setSalFacade(facade)
499 .setBaseSchemas(BASE_SCHEMAS)
501 final NetconfDevice netconfSpy = spy(device);
503 final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of());
505 final var moduleBasedCaps = new HashMap<QName, CapabilityOrigin>();
506 moduleBasedCaps.put(org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
507 .YangModuleInfoImpl.getInstance().getName(),
508 CapabilityOrigin.DeviceAdvertised);
509 moduleBasedCaps.put(org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
510 .YangModuleInfoImpl.getInstance().getName(),
511 CapabilityOrigin.DeviceAdvertised);
514 netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), listener);
516 final var argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
517 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
518 any(RemoteDeviceServices.class));
519 final Set<AvailableCapability> resolvedCapabilities = argument.getValue().capabilities().resolvedCapabilities();
521 final var notificationModulesName = List.of(
522 org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
523 .YangModuleInfoImpl.getInstance().getName().toString(),
524 org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
525 .YangModuleInfoImpl.getInstance().getName().toString());
527 assertEquals(2, resolvedCapabilities.size());
528 assertTrue(resolvedCapabilities.stream().anyMatch(entry -> notificationModulesName
529 .contains(entry.getCapability())));
532 private static EffectiveModelContextFactory getSchemaFactory() throws Exception {
533 final EffectiveModelContextFactory schemaFactory = mock(EffectiveModelContextFactory.class);
534 doReturn(Futures.immediateFuture(SCHEMA_CONTEXT))
535 .when(schemaFactory).createEffectiveModelContext(anyCollection());
536 return schemaFactory;
539 private static RemoteDeviceHandler getFacade() throws Exception {
540 final RemoteDeviceHandler remoteDeviceHandler = mockCloseableClass(RemoteDeviceHandler.class);
541 doNothing().when(remoteDeviceHandler).onDeviceConnected(
542 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
543 doNothing().when(remoteDeviceHandler).onDeviceDisconnected();
544 doNothing().when(remoteDeviceHandler).onNotification(any(DOMNotification.class));
545 return remoteDeviceHandler;
548 private static <T extends AutoCloseable> T mockCloseableClass(final Class<T> remoteDeviceHandlerClass)
550 final T mock = mock(remoteDeviceHandlerClass);
551 doNothing().when(mock).close();
555 public RemoteDeviceId getId() {
556 return new RemoteDeviceId("test-D", InetSocketAddress.createUnresolved("localhost", 22));
559 public NetconfSessionPreferences getSessionCaps(final boolean addMonitor,
560 final Collection<String> additionalCapabilities) {
561 final var capabilities = new ArrayList<String>();
562 capabilities.add(CapabilityURN.BASE);
563 capabilities.add(CapabilityURN.BASE_1_1);
565 capabilities.add(NetconfState.QNAME.getNamespace().toString());
567 capabilities.addAll(additionalCapabilities);
568 return NetconfSessionPreferences.fromStrings(capabilities);
571 public NetconfDeviceCommunicator getListener() throws Exception {
572 return mockCloseableClass(NetconfDeviceCommunicator.class);