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.collect.ImmutableMultimap;
29 import com.google.common.collect.Sets;
30 import com.google.common.util.concurrent.Futures;
31 import com.google.common.util.concurrent.MoreExecutors;
32 import com.google.common.util.concurrent.SettableFuture;
33 import java.net.InetSocketAddress;
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.HashMap;
37 import java.util.List;
40 import org.junit.BeforeClass;
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 import org.mockito.ArgumentCaptor;
44 import org.mockito.Mock;
45 import org.mockito.junit.MockitoJUnitRunner;
46 import org.opendaylight.mdsal.dom.api.DOMNotification;
47 import org.opendaylight.netconf.api.CapabilityURN;
48 import org.opendaylight.netconf.api.messages.NetconfMessage;
49 import org.opendaylight.netconf.api.xml.XmlUtil;
50 import org.opendaylight.netconf.client.mdsal.NetconfDevice.EmptySchemaContextException;
51 import org.opendaylight.netconf.client.mdsal.api.NetconfDeviceSchemasResolver;
52 import org.opendaylight.netconf.client.mdsal.api.NetconfSessionPreferences;
53 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceHandler;
54 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
55 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices;
56 import org.opendaylight.netconf.client.mdsal.impl.NetconfMessageTransformUtil;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev231121.connection.oper.available.capabilities.AvailableCapability;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev231121.connection.oper.available.capabilities.AvailableCapability.CapabilityOrigin;
59 import org.opendaylight.yangtools.yang.common.QName;
60 import org.opendaylight.yangtools.yang.model.api.Module;
61 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
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.api.SourceIdentifier;
67 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
68 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
69 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
71 @RunWith(MockitoJUnitRunner.StrictStubs.class)
72 public class NetconfDeviceTest extends AbstractTestModelTest {
73 public static final String TEST_NAMESPACE = "test:namespace";
74 public static final String TEST_MODULE = "test-module";
75 public static final String TEST_REVISION = "2013-07-22";
76 public static final SourceIdentifier TEST_SID = new SourceIdentifier(TEST_MODULE, TEST_REVISION);
77 public static final String TEST_CAPABILITY =
78 TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION;
80 public static final SourceIdentifier TEST_SID2 = new SourceIdentifier(TEST_MODULE + "2", TEST_REVISION);
81 public static final String TEST_CAPABILITY2 =
82 TEST_NAMESPACE + "?module=" + TEST_MODULE + "2" + "&revision=" + TEST_REVISION;
84 private static final NetconfDeviceSchemasResolver STATE_SCHEMAS_RESOLVER =
85 (deviceRpc, remoteSessionCapabilities, id, schemaContext) -> NetconfStateSchemas.EMPTY;
87 private static NetconfMessage NOTIFICATION;
90 private SchemaSourceRegistry schemaRegistry;
93 public static final void setupNotification() throws Exception {
94 NOTIFICATION = new NetconfMessage(XmlUtil.readXmlToDocument(
95 NetconfDeviceTest.class.getResourceAsStream("/notification-payload.xml")));
99 public void testNetconfDeviceFlawedModelFailedResolution() throws Exception {
100 final RemoteDeviceHandler facade = getFacade();
101 final NetconfDeviceCommunicator listener = getListener();
103 final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
104 final SchemaRepository schemaRepository = getSchemaRepository();
106 final SchemaResolutionException schemaResolutionException =
107 new SchemaResolutionException("fail first", TEST_SID, new Throwable("YangTools parser fail"));
108 doAnswer(invocation -> {
109 if (((Collection<?>) invocation.getArguments()[0]).size() == 2) {
110 return Futures.immediateFailedFuture(schemaResolutionException);
112 return Futures.immediateFuture(SCHEMA_CONTEXT);
114 }).when(schemaFactory).createEffectiveModelContext(anyCollection());
116 final NetconfDeviceSchemasResolver stateSchemasResolver = (deviceRpc, remoteSessionCapabilities, id,
118 final Module first = SCHEMA_CONTEXT.getModules().iterator().next();
119 final QName qName = QName.create(first.getQNameModule(), first.getName());
120 final NetconfStateSchemas.RemoteYangSchema source1 = new NetconfStateSchemas.RemoteYangSchema(qName);
121 final NetconfStateSchemas.RemoteYangSchema source2 =
122 new NetconfStateSchemas.RemoteYangSchema(QName.create(first.getQNameModule(), "test-module2"));
123 return new NetconfStateSchemas(Sets.newHashSet(source1, source2));
126 doReturn(mock(SchemaSourceRegistration.class)).when(schemaRegistry).registerSchemaSource(any(), any());
127 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
128 .SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaFactory, stateSchemasResolver);
130 final NetconfDevice device = new NetconfDeviceBuilder()
131 .setReconnectOnSchemasChange(true)
132 .setSchemaResourcesDTO(schemaResourcesDTO)
133 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
135 .setSalFacade(facade)
136 .setBaseSchemas(BASE_SCHEMAS)
138 // Monitoring supported
139 final NetconfSessionPreferences sessionCaps = getSessionCaps(true, List.of(TEST_CAPABILITY, TEST_CAPABILITY2));
140 device.onRemoteSessionUp(sessionCaps, listener);
142 verify(facade, timeout(5000)).onDeviceConnected(any(NetconfDeviceSchema.class),
143 any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
144 verify(schemaFactory, times(2)).createEffectiveModelContext(anyCollection());
148 public void testNetconfDeviceFailFirstSchemaFailSecondEmpty() throws Exception {
149 final RemoteDeviceHandler facade = getFacade();
150 final NetconfDeviceCommunicator listener = getListener();
152 final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
153 final SchemaRepository schemaRepository = getSchemaRepository();
155 // Make fallback attempt to fail due to empty resolved sources
156 final SchemaResolutionException schemaResolutionException = new SchemaResolutionException("fail first",
157 List.of(), ImmutableMultimap.of());
158 doReturn(Futures.immediateFailedFuture(schemaResolutionException))
159 .when(schemaFactory).createEffectiveModelContext(anyCollection());
161 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
162 .SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaFactory, STATE_SCHEMAS_RESOLVER);
163 final NetconfDevice device = new NetconfDeviceBuilder()
164 .setReconnectOnSchemasChange(true)
165 .setSchemaResourcesDTO(schemaResourcesDTO)
166 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
168 .setSalFacade(facade)
169 .setBaseSchemas(BASE_SCHEMAS)
172 // Monitoring not supported
173 final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of(TEST_CAPABILITY));
174 device.onRemoteSessionUp(sessionCaps, listener);
176 final var captor = ArgumentCaptor.forClass(Throwable.class);
177 verify(facade, timeout(5000)).onDeviceFailed(captor.capture());
178 assertThat(captor.getValue(), instanceOf(EmptySchemaContextException.class));
180 verify(listener, timeout(5000)).close();
181 verify(schemaFactory, times(1)).createEffectiveModelContext(anyCollection());
185 public void testNetconfDeviceMissingSource() throws Exception {
186 final RemoteDeviceHandler facade = getFacade();
187 final NetconfDeviceCommunicator listener = getListener();
189 final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
190 final SchemaRepository schemaRepository = getSchemaRepository();
192 // Make fallback attempt to fail due to empty resolved sources
193 final MissingSchemaSourceException schemaResolutionException =
194 new MissingSchemaSourceException("fail first", TEST_SID);
195 doReturn(Futures.immediateFailedFuture(schemaResolutionException))
196 .when(schemaRepository).getSchemaSource(eq(TEST_SID), eq(YangTextSchemaSource.class));
197 doAnswer(invocation -> {
198 if (((Collection<?>) invocation.getArguments()[0]).size() == 2) {
199 return Futures.immediateFailedFuture(schemaResolutionException);
201 return Futures.immediateFuture(SCHEMA_CONTEXT);
203 }).when(schemaFactory).createEffectiveModelContext(anyCollection());
205 final NetconfDeviceSchemasResolver stateSchemasResolver = (deviceRpc, remoteSessionCapabilities, id,
207 final Module first = SCHEMA_CONTEXT.getModules().iterator().next();
208 final QName qName = QName.create(first.getQNameModule(), first.getName());
209 final NetconfStateSchemas.RemoteYangSchema source1 = new NetconfStateSchemas.RemoteYangSchema(qName);
210 final NetconfStateSchemas.RemoteYangSchema source2 =
211 new NetconfStateSchemas.RemoteYangSchema(QName.create(first.getQNameModule(), "test-module2"));
212 return new NetconfStateSchemas(Sets.newHashSet(source1, source2));
215 doReturn(mock(SchemaSourceRegistration.class)).when(schemaRegistry).registerSchemaSource(any(), any());
216 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
217 .SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaFactory, stateSchemasResolver);
219 final NetconfDevice device = new NetconfDeviceBuilder()
220 .setReconnectOnSchemasChange(true)
221 .setSchemaResourcesDTO(schemaResourcesDTO)
222 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
223 .setBaseSchemas(BASE_SCHEMAS)
225 .setSalFacade(facade)
227 // Monitoring supported
228 final NetconfSessionPreferences sessionCaps =
229 getSessionCaps(true, List.of(TEST_CAPABILITY, TEST_CAPABILITY2));
230 device.onRemoteSessionUp(sessionCaps, listener);
232 verify(facade, timeout(5000)).onDeviceConnected(any(NetconfDeviceSchema.class),
233 any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
234 verify(schemaFactory, times(1)).createEffectiveModelContext(anyCollection());
237 private static SchemaRepository getSchemaRepository() {
238 final SchemaRepository mock = mock(SchemaRepository.class);
239 final YangTextSchemaSource mockRep = mock(YangTextSchemaSource.class);
240 doReturn(Futures.immediateFuture(mockRep))
241 .when(mock).getSchemaSource(any(SourceIdentifier.class), eq(YangTextSchemaSource.class));
246 public void testNotificationBeforeSchema() throws Exception {
247 final RemoteDeviceHandler facade = getFacade();
248 final NetconfDeviceCommunicator listener = getListener();
249 final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
250 final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
251 doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
252 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
253 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
254 final NetconfDevice device = new NetconfDeviceBuilder()
255 .setReconnectOnSchemasChange(true)
256 .setSchemaResourcesDTO(schemaResourcesDTO)
257 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
259 .setSalFacade(facade)
260 .setBaseSchemas(BASE_SCHEMAS)
263 final NetconfSessionPreferences sessionCaps = getSessionCaps(true, List.of(TEST_CAPABILITY));
264 device.onRemoteSessionUp(sessionCaps, listener);
266 device.onNotification(NOTIFICATION);
267 device.onNotification(NOTIFICATION);
268 verify(facade, times(0)).onNotification(any(DOMNotification.class));
270 verify(facade, times(0)).onNotification(any(DOMNotification.class));
271 schemaFuture.set(NetconfToNotificationTest.getNotificationSchemaContext(getClass(), false));
272 verify(facade, timeout(10000).times(2)).onNotification(any(DOMNotification.class));
274 device.onNotification(NOTIFICATION);
275 verify(facade, timeout(10000).times(3)).onNotification(any(DOMNotification.class));
279 public void testNetconfDeviceReconnect() throws Exception {
280 final RemoteDeviceHandler facade = getFacade();
281 final NetconfDeviceCommunicator listener = getListener();
283 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
285 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
286 schemaRegistry, getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
287 final NetconfDevice device = new NetconfDeviceBuilder()
288 .setReconnectOnSchemasChange(true)
289 .setSchemaResourcesDTO(schemaResourcesDTO)
290 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
292 .setSalFacade(facade)
293 .setBaseSchemas(BASE_SCHEMAS)
295 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
296 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
297 device.onRemoteSessionUp(sessionCaps, listener);
299 verify(schemaContextProviderFactory, timeout(5000)).createEffectiveModelContext(anyCollection());
300 verify(facade, timeout(5000)).onDeviceConnected(
301 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
303 device.onRemoteSessionDown();
304 verify(facade, timeout(5000)).onDeviceDisconnected();
306 device.onRemoteSessionUp(sessionCaps, listener);
308 verify(schemaContextProviderFactory, timeout(5000).times(2)).createEffectiveModelContext(anyCollection());
309 verify(facade, timeout(5000).times(2)).onDeviceConnected(
310 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
314 public void testNetconfDeviceDisconnectListenerCallCancellation() throws Exception {
315 final RemoteDeviceHandler facade = getFacade();
316 final NetconfDeviceCommunicator listener = getListener();
317 final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
318 final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
319 doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
320 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
321 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
322 final NetconfDevice device = new NetconfDeviceBuilder()
323 .setReconnectOnSchemasChange(true)
324 .setSchemaResourcesDTO(schemaResourcesDTO)
325 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
327 .setSalFacade(facade)
328 .setBaseSchemas(BASE_SCHEMAS)
330 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
331 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
332 //session up, start schema resolution
333 device.onRemoteSessionUp(sessionCaps, listener);
335 device.onRemoteSessionDown();
336 verify(facade, timeout(5000)).onDeviceDisconnected();
337 //complete schema setup
338 schemaFuture.set(SCHEMA_CONTEXT);
339 //facade.onDeviceDisconnected() was called, so facade.onDeviceConnected() shouldn't be called anymore
340 verify(facade, after(1000).never()).onDeviceConnected(any(), any(), any(RemoteDeviceServices.class));
344 public void testNetconfDeviceReconnectBeforeSchemaSetup() throws Exception {
345 final RemoteDeviceHandler facade = getFacade();
347 final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
348 final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
349 doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
351 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
352 schemaRegistry, getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
353 final NetconfDevice device = new NetconfDeviceBuilder()
354 .setReconnectOnSchemasChange(true)
355 .setSchemaResourcesDTO(schemaResourcesDTO)
356 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
358 .setSalFacade(facade)
359 .setBaseSchemas(BASE_SCHEMAS)
361 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
362 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
364 final NetconfDeviceCommunicator listener = getListener();
365 // session up, start schema resolution
366 device.onRemoteSessionUp(sessionCaps, listener);
368 device.onRemoteSessionDown();
369 verify(facade, timeout(5000)).onDeviceDisconnected();
370 // session back up, start another schema resolution
371 device.onRemoteSessionUp(sessionCaps, listener);
372 // complete schema setup
373 schemaFuture.set(SCHEMA_CONTEXT);
374 // schema setup performed twice
375 verify(schemaContextProviderFactory, timeout(5000).times(2)).createEffectiveModelContext(anyCollection());
376 // onDeviceConnected called once
377 verify(facade, timeout(5000)).onDeviceConnected(
378 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
382 public void testNetconfDeviceAvailableCapabilitiesBuilding() throws Exception {
383 final RemoteDeviceHandler facade = getFacade();
384 final NetconfDeviceCommunicator listener = getListener();
386 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
388 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
389 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
390 final NetconfDevice device = new NetconfDeviceBuilder()
391 .setReconnectOnSchemasChange(true)
392 .setSchemaResourcesDTO(schemaResourcesDTO)
393 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
395 .setSalFacade(facade)
396 .setBaseSchemas(BASE_SCHEMAS)
398 final NetconfDevice netconfSpy = spy(device);
400 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
401 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
402 final Map<QName, CapabilityOrigin> moduleBasedCaps = new HashMap<>();
403 moduleBasedCaps.putAll(sessionCaps.moduleBasedCaps());
405 .put(QName.create("(test:qname:side:loading)test"), CapabilityOrigin.UserDefined);
407 netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), listener);
409 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
410 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
411 any(RemoteDeviceServices.class));
412 argument.getValue().capabilities().resolvedCapabilities()
413 .forEach(entry -> assertEquals("Builded 'AvailableCapability' schemas should match input capabilities.",
415 QName.create(entry.getCapability())).getName(), entry.getCapabilityOrigin().getName()));
419 public void testNetconfDeviceNotificationsModelNotPresentWithCapability() throws Exception {
420 final RemoteDeviceHandler facade = getFacade();
421 final NetconfDeviceCommunicator listener = getListener();
422 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
424 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
425 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
426 final NetconfDevice device = new NetconfDeviceBuilder()
427 .setSchemaResourcesDTO(schemaResourcesDTO)
428 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
430 .setSalFacade(facade)
431 .setBaseSchemas(BASE_SCHEMAS)
433 final NetconfDevice netconfSpy = spy(device);
435 final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of(CapabilityURN.NOTIFICATION));
437 netconfSpy.onRemoteSessionUp(sessionCaps, listener);
439 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
440 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
441 any(RemoteDeviceServices.class));
443 List<String> notificationModulesName = List.of(
444 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
445 .$YangModuleInfoImpl.getInstance().getName().toString(),
446 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
447 .$YangModuleInfoImpl.getInstance().getName().toString());
449 final Set<AvailableCapability> resolvedCapabilities = argument.getValue().capabilities().resolvedCapabilities();
451 assertEquals(2, resolvedCapabilities.size());
452 assertTrue(resolvedCapabilities.stream().anyMatch(entry -> notificationModulesName
453 .contains(entry.getCapability())));
457 public void testNetconfDeviceNotificationsCapabilityIsNotPresent() throws Exception {
458 final RemoteDeviceHandler facade = getFacade();
459 final NetconfDeviceCommunicator listener = getListener();
460 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
462 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
463 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
464 final NetconfDevice device = new NetconfDeviceBuilder()
465 .setSchemaResourcesDTO(schemaResourcesDTO)
466 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
468 .setSalFacade(facade)
469 .setBaseSchemas(BASE_SCHEMAS)
471 final NetconfDevice netconfSpy = spy(device);
473 final NetconfSessionPreferences sessionCaps = getSessionCaps(false,
474 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
476 netconfSpy.onRemoteSessionUp(sessionCaps, listener);
478 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
479 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
480 any(RemoteDeviceServices.class));
481 final NetconfDeviceCapabilities netconfDeviceCaps = argument.getValue().capabilities();
483 List<String> notificationModulesName = List.of(
484 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
485 .$YangModuleInfoImpl.getInstance().getName().toString(),
486 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
487 .$YangModuleInfoImpl.getInstance().getName().toString());
489 assertFalse(netconfDeviceCaps.resolvedCapabilities().stream()
490 .anyMatch(entry -> notificationModulesName.contains(entry.getCapability())));
494 public void testNetconfDeviceNotificationsModelIsPresent() throws Exception {
495 final RemoteDeviceHandler facade = getFacade();
496 final NetconfDeviceCommunicator listener = getListener();
497 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
499 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
500 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
501 final NetconfDevice device = new NetconfDeviceBuilder()
502 .setSchemaResourcesDTO(schemaResourcesDTO)
503 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
505 .setSalFacade(facade)
506 .setBaseSchemas(BASE_SCHEMAS)
508 final NetconfDevice netconfSpy = spy(device);
510 final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of());
512 final Map<QName, CapabilityOrigin> moduleBasedCaps = new HashMap<>();
513 moduleBasedCaps.put(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
514 .$YangModuleInfoImpl.getInstance().getName(),
515 CapabilityOrigin.DeviceAdvertised);
516 moduleBasedCaps.put(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
517 .$YangModuleInfoImpl.getInstance().getName(),
518 CapabilityOrigin.DeviceAdvertised);
521 netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), listener);
523 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
524 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
525 any(RemoteDeviceServices.class));
526 final Set<AvailableCapability> resolvedCapabilities = argument.getValue().capabilities().resolvedCapabilities();
528 List<String> notificationModulesName = List.of(
529 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
530 .$YangModuleInfoImpl.getInstance().getName().toString(),
531 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
532 .$YangModuleInfoImpl.getInstance().getName().toString());
534 assertEquals(2, resolvedCapabilities.size());
535 assertTrue(resolvedCapabilities.stream().anyMatch(entry -> notificationModulesName
536 .contains(entry.getCapability())));
539 private static EffectiveModelContextFactory getSchemaFactory() throws Exception {
540 final EffectiveModelContextFactory schemaFactory = mock(EffectiveModelContextFactory.class);
541 doReturn(Futures.immediateFuture(SCHEMA_CONTEXT))
542 .when(schemaFactory).createEffectiveModelContext(anyCollection());
543 return schemaFactory;
546 private static RemoteDeviceHandler getFacade() throws Exception {
547 final RemoteDeviceHandler remoteDeviceHandler = mockCloseableClass(RemoteDeviceHandler.class);
548 doNothing().when(remoteDeviceHandler).onDeviceConnected(
549 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
550 doNothing().when(remoteDeviceHandler).onDeviceDisconnected();
551 doNothing().when(remoteDeviceHandler).onNotification(any(DOMNotification.class));
552 return remoteDeviceHandler;
555 private static <T extends AutoCloseable> T mockCloseableClass(final Class<T> remoteDeviceHandlerClass)
557 final T mock = mock(remoteDeviceHandlerClass);
558 doNothing().when(mock).close();
562 public RemoteDeviceId getId() {
563 return new RemoteDeviceId("test-D", InetSocketAddress.createUnresolved("localhost", 22));
566 public NetconfSessionPreferences getSessionCaps(final boolean addMonitor,
567 final Collection<String> additionalCapabilities) {
568 final var capabilities = new ArrayList<String>();
569 capabilities.add(CapabilityURN.BASE);
570 capabilities.add(CapabilityURN.BASE_1_1);
572 capabilities.add(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING.getNamespace().toString());
574 capabilities.addAll(additionalCapabilities);
575 return NetconfSessionPreferences.fromStrings(capabilities);
578 public NetconfDeviceCommunicator getListener() throws Exception {
579 return mockCloseableClass(NetconfDeviceCommunicator.class);