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.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertTrue;
13 import static org.mockito.ArgumentMatchers.any;
14 import static org.mockito.ArgumentMatchers.anyCollection;
15 import static org.mockito.ArgumentMatchers.eq;
16 import static org.mockito.Mockito.after;
17 import static org.mockito.Mockito.doAnswer;
18 import static org.mockito.Mockito.doNothing;
19 import static org.mockito.Mockito.doReturn;
20 import static org.mockito.Mockito.mock;
21 import static org.mockito.Mockito.spy;
22 import static org.mockito.Mockito.timeout;
23 import static org.mockito.Mockito.times;
24 import static org.mockito.Mockito.verify;
26 import com.google.common.collect.ImmutableMultimap;
27 import com.google.common.collect.Sets;
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.io.IOException;
32 import java.net.InetSocketAddress;
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.HashMap;
36 import java.util.List;
39 import org.junit.Test;
40 import org.mockito.ArgumentCaptor;
41 import org.opendaylight.mdsal.dom.api.DOMNotification;
42 import org.opendaylight.netconf.api.CapabilityURN;
43 import org.opendaylight.netconf.api.NetconfMessage;
44 import org.opendaylight.netconf.api.xml.XmlUtil;
45 import org.opendaylight.netconf.client.mdsal.api.NetconfDeviceSchemasResolver;
46 import org.opendaylight.netconf.client.mdsal.api.NetconfSessionPreferences;
47 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceHandler;
48 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
49 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices;
50 import org.opendaylight.netconf.client.mdsal.impl.NetconfMessageTransformUtil;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.connection.oper.available.capabilities.AvailableCapability;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.connection.oper.available.capabilities.AvailableCapability.CapabilityOrigin;
53 import org.opendaylight.yangtools.yang.common.QName;
54 import org.opendaylight.yangtools.yang.model.api.Module;
55 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
56 import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
57 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
58 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
59 import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
60 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
61 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
62 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
63 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
64 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
65 import org.xml.sax.SAXException;
67 public class NetconfDeviceTest extends AbstractTestModelTest {
68 private static final NetconfMessage NOTIFICATION;
72 NOTIFICATION = new NetconfMessage(XmlUtil
73 .readXmlToDocument(NetconfDeviceTest.class.getResourceAsStream("/notification-payload.xml")));
74 } catch (SAXException | IOException e) {
75 throw new ExceptionInInitializerError(e);
79 public static final String TEST_NAMESPACE = "test:namespace";
80 public static final String TEST_MODULE = "test-module";
81 public static final String TEST_REVISION = "2013-07-22";
82 public static final SourceIdentifier TEST_SID = new SourceIdentifier(TEST_MODULE, TEST_REVISION);
83 public static final String TEST_CAPABILITY =
84 TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION;
86 public static final SourceIdentifier TEST_SID2 = new SourceIdentifier(TEST_MODULE + "2", TEST_REVISION);
87 public static final String TEST_CAPABILITY2 =
88 TEST_NAMESPACE + "?module=" + TEST_MODULE + "2" + "&revision=" + TEST_REVISION;
90 private static final NetconfDeviceSchemasResolver STATE_SCHEMAS_RESOLVER =
91 (deviceRpc, remoteSessionCapabilities, id, schemaContext) -> NetconfStateSchemas.EMPTY;
95 public void testNetconfDeviceFlawedModelFailedResolution() throws Exception {
96 final RemoteDeviceHandler facade = getFacade();
97 final NetconfDeviceCommunicator listener = getListener();
99 final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
100 final SchemaRepository schemaRepository = getSchemaRepository();
102 final SchemaResolutionException schemaResolutionException =
103 new SchemaResolutionException("fail first", TEST_SID, new Throwable("YangTools parser fail"));
104 doAnswer(invocation -> {
105 if (((Collection<?>) invocation.getArguments()[0]).size() == 2) {
106 return Futures.immediateFailedFuture(schemaResolutionException);
108 return Futures.immediateFuture(SCHEMA_CONTEXT);
110 }).when(schemaFactory).createEffectiveModelContext(anyCollection());
112 final NetconfDeviceSchemasResolver stateSchemasResolver = (deviceRpc, remoteSessionCapabilities, id,
114 final Module first = SCHEMA_CONTEXT.getModules().iterator().next();
115 final QName qName = QName.create(first.getQNameModule(), first.getName());
116 final NetconfStateSchemas.RemoteYangSchema source1 = new NetconfStateSchemas.RemoteYangSchema(qName);
117 final NetconfStateSchemas.RemoteYangSchema source2 =
118 new NetconfStateSchemas.RemoteYangSchema(QName.create(first.getQNameModule(), "test-module2"));
119 return new NetconfStateSchemas(Sets.newHashSet(source1, source2));
122 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
123 .SchemaResourcesDTO(getSchemaRegistry(), 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 List.of(), ImmutableMultimap.of());
153 doReturn(Futures.immediateFailedFuture(schemaResolutionException))
154 .when(schemaFactory).createEffectiveModelContext(anyCollection());
156 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
157 .SchemaResourcesDTO(getSchemaRegistry(), 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 verify(facade, timeout(5000)).onDeviceDisconnected();
172 verify(listener, timeout(5000)).close();
173 verify(schemaFactory, times(1)).createEffectiveModelContext(anyCollection());
177 public void testNetconfDeviceMissingSource() throws Exception {
178 final RemoteDeviceHandler facade = getFacade();
179 final NetconfDeviceCommunicator listener = getListener();
181 final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
182 final SchemaRepository schemaRepository = getSchemaRepository();
184 // Make fallback attempt to fail due to empty resolved sources
185 final MissingSchemaSourceException schemaResolutionException =
186 new MissingSchemaSourceException("fail first", TEST_SID);
187 doReturn(Futures.immediateFailedFuture(schemaResolutionException))
188 .when(schemaRepository).getSchemaSource(eq(TEST_SID), eq(YangTextSchemaSource.class));
189 doAnswer(invocation -> {
190 if (((Collection<?>) invocation.getArguments()[0]).size() == 2) {
191 return Futures.immediateFailedFuture(schemaResolutionException);
193 return Futures.immediateFuture(SCHEMA_CONTEXT);
195 }).when(schemaFactory).createEffectiveModelContext(anyCollection());
197 final NetconfDeviceSchemasResolver stateSchemasResolver = (deviceRpc, remoteSessionCapabilities, id,
199 final Module first = SCHEMA_CONTEXT.getModules().iterator().next();
200 final QName qName = QName.create(first.getQNameModule(), first.getName());
201 final NetconfStateSchemas.RemoteYangSchema source1 = new NetconfStateSchemas.RemoteYangSchema(qName);
202 final NetconfStateSchemas.RemoteYangSchema source2 =
203 new NetconfStateSchemas.RemoteYangSchema(QName.create(first.getQNameModule(), "test-module2"));
204 return new NetconfStateSchemas(Sets.newHashSet(source1, source2));
207 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
208 .SchemaResourcesDTO(getSchemaRegistry(), schemaRepository, schemaFactory, stateSchemasResolver);
210 final NetconfDevice device = new NetconfDeviceBuilder()
211 .setReconnectOnSchemasChange(true)
212 .setSchemaResourcesDTO(schemaResourcesDTO)
213 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
214 .setBaseSchemas(BASE_SCHEMAS)
216 .setSalFacade(facade)
218 // Monitoring supported
219 final NetconfSessionPreferences sessionCaps =
220 getSessionCaps(true, List.of(TEST_CAPABILITY, TEST_CAPABILITY2));
221 device.onRemoteSessionUp(sessionCaps, listener);
223 verify(facade, timeout(5000)).onDeviceConnected(any(NetconfDeviceSchema.class),
224 any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
225 verify(schemaFactory, times(1)).createEffectiveModelContext(anyCollection());
228 private static SchemaSourceRegistry getSchemaRegistry() {
229 final SchemaSourceRegistry mock = mock(SchemaSourceRegistry.class);
230 final SchemaSourceRegistration<?> mockReg = mock(SchemaSourceRegistration.class);
231 doNothing().when(mockReg).close();
232 doReturn(mockReg).when(mock).registerSchemaSource(
233 any(org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider.class),
234 any(PotentialSchemaSource.class));
238 private static SchemaRepository getSchemaRepository() {
239 final SchemaRepository mock = mock(SchemaRepository.class);
240 final YangTextSchemaSource mockRep = mock(YangTextSchemaSource.class);
241 doReturn(Futures.immediateFuture(mockRep))
242 .when(mock).getSchemaSource(any(SourceIdentifier.class), eq(YangTextSchemaSource.class));
247 public void testNotificationBeforeSchema() throws Exception {
248 final RemoteDeviceHandler facade = getFacade();
249 final NetconfDeviceCommunicator listener = getListener();
250 final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
251 final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
252 doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
253 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO =
254 new NetconfDevice.SchemaResourcesDTO(getSchemaRegistry(), getSchemaRepository(),
255 schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
256 final NetconfDevice device = new NetconfDeviceBuilder()
257 .setReconnectOnSchemasChange(true)
258 .setSchemaResourcesDTO(schemaResourcesDTO)
259 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
261 .setSalFacade(facade)
262 .setBaseSchemas(BASE_SCHEMAS)
265 final NetconfSessionPreferences sessionCaps = getSessionCaps(true, List.of(TEST_CAPABILITY));
266 device.onRemoteSessionUp(sessionCaps, listener);
268 device.onNotification(NOTIFICATION);
269 device.onNotification(NOTIFICATION);
270 verify(facade, times(0)).onNotification(any(DOMNotification.class));
272 verify(facade, times(0)).onNotification(any(DOMNotification.class));
273 schemaFuture.set(NetconfToNotificationTest.getNotificationSchemaContext(getClass(), false));
274 verify(facade, timeout(10000).times(2)).onNotification(any(DOMNotification.class));
276 device.onNotification(NOTIFICATION);
277 verify(facade, timeout(10000).times(3)).onNotification(any(DOMNotification.class));
281 public void testNetconfDeviceReconnect() throws Exception {
282 final RemoteDeviceHandler facade = getFacade();
283 final NetconfDeviceCommunicator listener = getListener();
285 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
287 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
288 getSchemaRegistry(), getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
289 final NetconfDevice device = new NetconfDeviceBuilder()
290 .setReconnectOnSchemasChange(true)
291 .setSchemaResourcesDTO(schemaResourcesDTO)
292 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
294 .setSalFacade(facade)
295 .setBaseSchemas(BASE_SCHEMAS)
297 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
298 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
299 device.onRemoteSessionUp(sessionCaps, listener);
301 verify(schemaContextProviderFactory, timeout(5000)).createEffectiveModelContext(anyCollection());
302 verify(facade, timeout(5000)).onDeviceConnected(
303 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
305 device.onRemoteSessionDown();
306 verify(facade, timeout(5000)).onDeviceDisconnected();
308 device.onRemoteSessionUp(sessionCaps, listener);
310 verify(schemaContextProviderFactory, timeout(5000).times(2)).createEffectiveModelContext(anyCollection());
311 verify(facade, timeout(5000).times(2)).onDeviceConnected(
312 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
316 public void testNetconfDeviceDisconnectListenerCallCancellation() throws Exception {
317 final RemoteDeviceHandler facade = getFacade();
318 final NetconfDeviceCommunicator listener = getListener();
319 final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
320 final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
321 doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
322 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO
323 = new NetconfDevice.SchemaResourcesDTO(getSchemaRegistry(), getSchemaRepository(),
324 schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
325 final NetconfDevice device = new NetconfDeviceBuilder()
326 .setReconnectOnSchemasChange(true)
327 .setSchemaResourcesDTO(schemaResourcesDTO)
328 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
330 .setSalFacade(facade)
331 .setBaseSchemas(BASE_SCHEMAS)
333 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
334 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
335 //session up, start schema resolution
336 device.onRemoteSessionUp(sessionCaps, listener);
338 device.onRemoteSessionDown();
339 verify(facade, timeout(5000)).onDeviceDisconnected();
340 //complete schema setup
341 schemaFuture.set(SCHEMA_CONTEXT);
342 //facade.onDeviceDisconnected() was called, so facade.onDeviceConnected() shouldn't be called anymore
343 verify(facade, after(1000).never()).onDeviceConnected(any(), any(), any(RemoteDeviceServices.class));
347 public void testNetconfDeviceAvailableCapabilitiesBuilding() throws Exception {
348 final RemoteDeviceHandler facade = getFacade();
349 final NetconfDeviceCommunicator listener = getListener();
351 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
353 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
354 getSchemaRegistry(), getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
355 final NetconfDevice device = new NetconfDeviceBuilder()
356 .setReconnectOnSchemasChange(true)
357 .setSchemaResourcesDTO(schemaResourcesDTO)
358 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
360 .setSalFacade(facade)
361 .setBaseSchemas(BASE_SCHEMAS)
363 final NetconfDevice netconfSpy = spy(device);
365 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
366 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
367 final Map<QName, CapabilityOrigin> moduleBasedCaps = new HashMap<>();
368 moduleBasedCaps.putAll(sessionCaps.moduleBasedCaps());
370 .put(QName.create("(test:qname:side:loading)test"), CapabilityOrigin.UserDefined);
372 netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), listener);
374 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
375 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
376 any(RemoteDeviceServices.class));
377 argument.getValue().capabilities().resolvedCapabilities()
378 .forEach(entry -> assertEquals("Builded 'AvailableCapability' schemas should match input capabilities.",
380 QName.create(entry.getCapability())).getName(), entry.getCapabilityOrigin().getName()));
384 public void testNetconfDeviceNotificationsModelNotPresentWithCapability() throws Exception {
385 final RemoteDeviceHandler facade = getFacade();
386 final NetconfDeviceCommunicator listener = getListener();
387 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
389 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
390 getSchemaRegistry(), getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
391 final NetconfDevice device = new NetconfDeviceBuilder()
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(false, List.of(CapabilityURN.NOTIFICATION));
402 netconfSpy.onRemoteSessionUp(sessionCaps, listener);
404 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
405 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
406 any(RemoteDeviceServices.class));
408 List<String> notificationModulesName = List.of(
409 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
410 .$YangModuleInfoImpl.getInstance().getName().toString(),
411 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
412 .$YangModuleInfoImpl.getInstance().getName().toString());
414 final Set<AvailableCapability> resolvedCapabilities = argument.getValue().capabilities().resolvedCapabilities();
416 assertEquals(2, resolvedCapabilities.size());
417 assertTrue(resolvedCapabilities.stream().anyMatch(entry -> notificationModulesName
418 .contains(entry.getCapability())));
422 public void testNetconfDeviceNotificationsCapabilityIsNotPresent() throws Exception {
423 final RemoteDeviceHandler facade = getFacade();
424 final NetconfDeviceCommunicator listener = getListener();
425 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
427 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
428 getSchemaRegistry(), getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
429 final NetconfDevice device = new NetconfDeviceBuilder()
430 .setSchemaResourcesDTO(schemaResourcesDTO)
431 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
433 .setSalFacade(facade)
434 .setBaseSchemas(BASE_SCHEMAS)
436 final NetconfDevice netconfSpy = spy(device);
438 final NetconfSessionPreferences sessionCaps = getSessionCaps(false,
439 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
441 netconfSpy.onRemoteSessionUp(sessionCaps, listener);
443 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
444 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
445 any(RemoteDeviceServices.class));
446 final NetconfDeviceCapabilities netconfDeviceCaps = argument.getValue().capabilities();
448 List<String> notificationModulesName = List.of(
449 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
450 .$YangModuleInfoImpl.getInstance().getName().toString(),
451 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
452 .$YangModuleInfoImpl.getInstance().getName().toString());
454 assertFalse(netconfDeviceCaps.resolvedCapabilities().stream()
455 .anyMatch(entry -> notificationModulesName.contains(entry.getCapability())));
459 public void testNetconfDeviceNotificationsModelIsPresent() throws Exception {
460 final RemoteDeviceHandler facade = getFacade();
461 final NetconfDeviceCommunicator listener = getListener();
462 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
464 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
465 getSchemaRegistry(), getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
466 final NetconfDevice device = new NetconfDeviceBuilder()
467 .setSchemaResourcesDTO(schemaResourcesDTO)
468 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
470 .setSalFacade(facade)
471 .setBaseSchemas(BASE_SCHEMAS)
473 final NetconfDevice netconfSpy = spy(device);
475 final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of());
477 final Map<QName, CapabilityOrigin> moduleBasedCaps = new HashMap<>();
478 moduleBasedCaps.put(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
479 .$YangModuleInfoImpl.getInstance().getName(),
480 CapabilityOrigin.DeviceAdvertised);
481 moduleBasedCaps.put(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
482 .$YangModuleInfoImpl.getInstance().getName(),
483 CapabilityOrigin.DeviceAdvertised);
486 netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), listener);
488 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
489 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
490 any(RemoteDeviceServices.class));
491 final Set<AvailableCapability> resolvedCapabilities = argument.getValue().capabilities().resolvedCapabilities();
493 List<String> notificationModulesName = List.of(
494 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
495 .$YangModuleInfoImpl.getInstance().getName().toString(),
496 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
497 .$YangModuleInfoImpl.getInstance().getName().toString());
499 assertEquals(2, resolvedCapabilities.size());
500 assertTrue(resolvedCapabilities.stream().anyMatch(entry -> notificationModulesName
501 .contains(entry.getCapability())));
504 private static EffectiveModelContextFactory getSchemaFactory() throws Exception {
505 final EffectiveModelContextFactory schemaFactory = mockClass(EffectiveModelContextFactory.class);
506 doReturn(Futures.immediateFuture(SCHEMA_CONTEXT))
507 .when(schemaFactory).createEffectiveModelContext(anyCollection());
508 return schemaFactory;
511 private static RemoteDeviceHandler getFacade() throws Exception {
512 final RemoteDeviceHandler remoteDeviceHandler = mockCloseableClass(RemoteDeviceHandler.class);
513 doNothing().when(remoteDeviceHandler).onDeviceConnected(
514 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
515 doNothing().when(remoteDeviceHandler).onDeviceDisconnected();
516 doNothing().when(remoteDeviceHandler).onNotification(any(DOMNotification.class));
517 return remoteDeviceHandler;
520 private static <T extends AutoCloseable> T mockCloseableClass(final Class<T> remoteDeviceHandlerClass)
522 final T mock = mockClass(remoteDeviceHandlerClass);
523 doNothing().when(mock).close();
527 private static <T> T mockClass(final Class<T> remoteDeviceHandlerClass) {
528 final T mock = mock(remoteDeviceHandlerClass);
529 doReturn(remoteDeviceHandlerClass.getSimpleName()).when(mock).toString();
533 public RemoteDeviceId getId() {
534 return new RemoteDeviceId("test-D", InetSocketAddress.createUnresolved("localhost", 22));
537 public NetconfSessionPreferences getSessionCaps(final boolean addMonitor,
538 final Collection<String> additionalCapabilities) {
539 final var capabilities = new ArrayList<String>();
540 capabilities.add(CapabilityURN.BASE);
541 capabilities.add(CapabilityURN.BASE_1_1);
543 capabilities.add(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING.getNamespace().toString());
545 capabilities.addAll(additionalCapabilities);
546 return NetconfSessionPreferences.fromStrings(capabilities);
549 public NetconfDeviceCommunicator getListener() throws Exception {
550 return mockCloseableClass(NetconfDeviceCommunicator.class);