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.ListeningExecutorService;
30 import com.google.common.util.concurrent.MoreExecutors;
31 import com.google.common.util.concurrent.SettableFuture;
32 import java.io.IOException;
33 import java.net.InetSocketAddress;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.HashMap;
39 import java.util.List;
42 import java.util.concurrent.Executors;
43 import org.junit.Test;
44 import org.mockito.ArgumentCaptor;
45 import org.opendaylight.mdsal.dom.api.DOMNotification;
46 import org.opendaylight.netconf.api.CapabilityURN;
47 import org.opendaylight.netconf.api.NetconfMessage;
48 import org.opendaylight.netconf.api.xml.XmlUtil;
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.netconf.client.mdsal.impl.NetconfMessageTransformUtil;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.connection.oper.available.capabilities.AvailableCapability;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.connection.oper.available.capabilities.AvailableCapability.CapabilityOrigin;
57 import org.opendaylight.yangtools.yang.common.QName;
58 import org.opendaylight.yangtools.yang.model.api.Module;
59 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
60 import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
61 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
62 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
63 import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
64 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
65 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
66 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
67 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
68 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
69 import org.xml.sax.SAXException;
71 public class NetconfDeviceTest extends AbstractTestModelTest {
72 private static final NetconfMessage NOTIFICATION;
76 NOTIFICATION = new NetconfMessage(XmlUtil
77 .readXmlToDocument(NetconfDeviceTest.class.getResourceAsStream("/notification-payload.xml")));
78 } catch (SAXException | IOException e) {
79 throw new ExceptionInInitializerError(e);
83 public static final String TEST_NAMESPACE = "test:namespace";
84 public static final String TEST_MODULE = "test-module";
85 public static final String TEST_REVISION = "2013-07-22";
86 public static final SourceIdentifier TEST_SID = new SourceIdentifier(TEST_MODULE, TEST_REVISION);
87 public static final String TEST_CAPABILITY =
88 TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION;
90 public static final SourceIdentifier TEST_SID2 = new SourceIdentifier(TEST_MODULE + "2", TEST_REVISION);
91 public static final String TEST_CAPABILITY2 =
92 TEST_NAMESPACE + "?module=" + TEST_MODULE + "2" + "&revision=" + TEST_REVISION;
94 private static final NetconfDeviceSchemasResolver STATE_SCHEMAS_RESOLVER =
95 (deviceRpc, remoteSessionCapabilities, id, schemaContext) -> NetconfStateSchemas.EMPTY;
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 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
127 .SchemaResourcesDTO(getSchemaRegistry(), schemaRepository, schemaFactory, stateSchemasResolver);
129 final NetconfDevice device = new NetconfDeviceBuilder()
130 .setReconnectOnSchemasChange(true)
131 .setSchemaResourcesDTO(schemaResourcesDTO)
132 .setGlobalProcessingExecutor(getExecutor())
134 .setSalFacade(facade)
135 .setBaseSchemas(BASE_SCHEMAS)
137 // Monitoring supported
138 final NetconfSessionPreferences sessionCaps = getSessionCaps(true, List.of(TEST_CAPABILITY, TEST_CAPABILITY2));
139 device.onRemoteSessionUp(sessionCaps, listener);
141 verify(facade, timeout(5000)).onDeviceConnected(any(NetconfDeviceSchema.class),
142 any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
143 verify(schemaFactory, times(2)).createEffectiveModelContext(anyCollection());
147 public void testNetconfDeviceFailFirstSchemaFailSecondEmpty() throws Exception {
148 final RemoteDeviceHandler facade = getFacade();
149 final NetconfDeviceCommunicator listener = getListener();
151 final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
152 final SchemaRepository schemaRepository = getSchemaRepository();
154 // Make fallback attempt to fail due to empty resolved sources
155 final SchemaResolutionException schemaResolutionException = new SchemaResolutionException("fail first",
156 List.of(), ImmutableMultimap.of());
157 doReturn(Futures.immediateFailedFuture(schemaResolutionException))
158 .when(schemaFactory).createEffectiveModelContext(anyCollection());
160 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
161 .SchemaResourcesDTO(getSchemaRegistry(), schemaRepository, schemaFactory, STATE_SCHEMAS_RESOLVER);
162 final NetconfDevice device = new NetconfDeviceBuilder()
163 .setReconnectOnSchemasChange(true)
164 .setSchemaResourcesDTO(schemaResourcesDTO)
165 .setGlobalProcessingExecutor(getExecutor())
167 .setSalFacade(facade)
168 .setBaseSchemas(BASE_SCHEMAS)
171 // Monitoring not supported
172 final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of(TEST_CAPABILITY));
173 device.onRemoteSessionUp(sessionCaps, listener);
175 verify(facade, timeout(5000)).onDeviceDisconnected();
176 verify(listener, timeout(5000)).close();
177 verify(schemaFactory, times(1)).createEffectiveModelContext(anyCollection());
181 public void testNetconfDeviceMissingSource() throws Exception {
182 final RemoteDeviceHandler facade = getFacade();
183 final NetconfDeviceCommunicator listener = getListener();
185 final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
186 final SchemaRepository schemaRepository = getSchemaRepository();
188 // Make fallback attempt to fail due to empty resolved sources
189 final MissingSchemaSourceException schemaResolutionException =
190 new MissingSchemaSourceException("fail first", TEST_SID);
191 doReturn(Futures.immediateFailedFuture(schemaResolutionException))
192 .when(schemaRepository).getSchemaSource(eq(TEST_SID), eq(YangTextSchemaSource.class));
193 doAnswer(invocation -> {
194 if (((Collection<?>) invocation.getArguments()[0]).size() == 2) {
195 return Futures.immediateFailedFuture(schemaResolutionException);
197 return Futures.immediateFuture(SCHEMA_CONTEXT);
199 }).when(schemaFactory).createEffectiveModelContext(anyCollection());
201 final NetconfDeviceSchemasResolver stateSchemasResolver = (deviceRpc, remoteSessionCapabilities, id,
203 final Module first = SCHEMA_CONTEXT.getModules().iterator().next();
204 final QName qName = QName.create(first.getQNameModule(), first.getName());
205 final NetconfStateSchemas.RemoteYangSchema source1 = new NetconfStateSchemas.RemoteYangSchema(qName);
206 final NetconfStateSchemas.RemoteYangSchema source2 =
207 new NetconfStateSchemas.RemoteYangSchema(QName.create(first.getQNameModule(), "test-module2"));
208 return new NetconfStateSchemas(Sets.newHashSet(source1, source2));
211 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
212 .SchemaResourcesDTO(getSchemaRegistry(), schemaRepository, schemaFactory, stateSchemasResolver);
214 final NetconfDevice device = new NetconfDeviceBuilder()
215 .setReconnectOnSchemasChange(true)
216 .setSchemaResourcesDTO(schemaResourcesDTO)
217 .setGlobalProcessingExecutor(getExecutor())
218 .setBaseSchemas(BASE_SCHEMAS)
220 .setSalFacade(facade)
222 // Monitoring supported
223 final NetconfSessionPreferences sessionCaps =
224 getSessionCaps(true, List.of(TEST_CAPABILITY, TEST_CAPABILITY2));
225 device.onRemoteSessionUp(sessionCaps, listener);
227 verify(facade, timeout(5000)).onDeviceConnected(any(NetconfDeviceSchema.class),
228 any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
229 verify(schemaFactory, times(1)).createEffectiveModelContext(anyCollection());
232 private static SchemaSourceRegistry getSchemaRegistry() {
233 final SchemaSourceRegistry mock = mock(SchemaSourceRegistry.class);
234 final SchemaSourceRegistration<?> mockReg = mock(SchemaSourceRegistration.class);
235 doNothing().when(mockReg).close();
236 doReturn(mockReg).when(mock).registerSchemaSource(
237 any(org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider.class),
238 any(PotentialSchemaSource.class));
242 private static SchemaRepository getSchemaRepository() {
243 final SchemaRepository mock = mock(SchemaRepository.class);
244 final YangTextSchemaSource mockRep = mock(YangTextSchemaSource.class);
245 doReturn(Futures.immediateFuture(mockRep))
246 .when(mock).getSchemaSource(any(SourceIdentifier.class), eq(YangTextSchemaSource.class));
251 public void testNotificationBeforeSchema() throws Exception {
252 final RemoteDeviceHandler facade = getFacade();
253 final NetconfDeviceCommunicator listener = getListener();
254 final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
255 final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
256 doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
257 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO =
258 new NetconfDevice.SchemaResourcesDTO(getSchemaRegistry(), getSchemaRepository(),
259 schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
260 final NetconfDevice device = new NetconfDeviceBuilder()
261 .setReconnectOnSchemasChange(true)
262 .setSchemaResourcesDTO(schemaResourcesDTO)
263 .setGlobalProcessingExecutor(getExecutor())
265 .setSalFacade(facade)
266 .setBaseSchemas(BASE_SCHEMAS)
269 final NetconfSessionPreferences sessionCaps = getSessionCaps(true, List.of(TEST_CAPABILITY));
270 device.onRemoteSessionUp(sessionCaps, listener);
272 device.onNotification(NOTIFICATION);
273 device.onNotification(NOTIFICATION);
274 verify(facade, times(0)).onNotification(any(DOMNotification.class));
276 verify(facade, times(0)).onNotification(any(DOMNotification.class));
277 schemaFuture.set(NetconfToNotificationTest.getNotificationSchemaContext(getClass(), false));
278 verify(facade, timeout(10000).times(2)).onNotification(any(DOMNotification.class));
280 device.onNotification(NOTIFICATION);
281 verify(facade, timeout(10000).times(3)).onNotification(any(DOMNotification.class));
285 public void testNetconfDeviceReconnect() throws Exception {
286 final RemoteDeviceHandler facade = getFacade();
287 final NetconfDeviceCommunicator listener = getListener();
289 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
291 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
292 getSchemaRegistry(), getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
293 final NetconfDevice device = new NetconfDeviceBuilder()
294 .setReconnectOnSchemasChange(true)
295 .setSchemaResourcesDTO(schemaResourcesDTO)
296 .setGlobalProcessingExecutor(getExecutor())
298 .setSalFacade(facade)
299 .setBaseSchemas(BASE_SCHEMAS)
301 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
302 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
303 device.onRemoteSessionUp(sessionCaps, listener);
305 verify(schemaContextProviderFactory, timeout(5000)).createEffectiveModelContext(anyCollection());
306 verify(facade, timeout(5000)).onDeviceConnected(
307 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
309 device.onRemoteSessionDown();
310 verify(facade, timeout(5000)).onDeviceDisconnected();
312 device.onRemoteSessionUp(sessionCaps, listener);
314 verify(schemaContextProviderFactory, timeout(5000).times(2)).createEffectiveModelContext(anyCollection());
315 verify(facade, timeout(5000).times(2)).onDeviceConnected(
316 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
320 public void testNetconfDeviceDisconnectListenerCallCancellation() throws Exception {
321 final RemoteDeviceHandler facade = getFacade();
322 final NetconfDeviceCommunicator listener = getListener();
323 final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
324 final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
325 doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
326 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO
327 = new NetconfDevice.SchemaResourcesDTO(getSchemaRegistry(), getSchemaRepository(),
328 schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
329 final NetconfDevice device = new NetconfDeviceBuilder()
330 .setReconnectOnSchemasChange(true)
331 .setSchemaResourcesDTO(schemaResourcesDTO)
332 .setGlobalProcessingExecutor(getExecutor())
334 .setSalFacade(facade)
335 .setBaseSchemas(BASE_SCHEMAS)
337 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
338 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
339 //session up, start schema resolution
340 device.onRemoteSessionUp(sessionCaps, listener);
342 device.onRemoteSessionDown();
343 verify(facade, timeout(5000)).onDeviceDisconnected();
344 //complete schema setup
345 schemaFuture.set(SCHEMA_CONTEXT);
346 //facade.onDeviceDisconnected() was called, so facade.onDeviceConnected() shouldn't be called anymore
347 verify(facade, after(1000).never()).onDeviceConnected(any(), any(), any(RemoteDeviceServices.class));
351 public void testNetconfDeviceAvailableCapabilitiesBuilding() throws Exception {
352 final RemoteDeviceHandler facade = getFacade();
353 final NetconfDeviceCommunicator listener = getListener();
355 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
357 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
358 getSchemaRegistry(), getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
359 final NetconfDevice device = new NetconfDeviceBuilder()
360 .setReconnectOnSchemasChange(true)
361 .setSchemaResourcesDTO(schemaResourcesDTO)
362 .setGlobalProcessingExecutor(getExecutor())
364 .setSalFacade(facade)
365 .setBaseSchemas(BASE_SCHEMAS)
367 final NetconfDevice netconfSpy = spy(device);
369 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
370 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
371 final Map<QName, CapabilityOrigin> moduleBasedCaps = new HashMap<>();
372 moduleBasedCaps.putAll(sessionCaps.moduleBasedCaps());
374 .put(QName.create("(test:qname:side:loading)test"), CapabilityOrigin.UserDefined);
376 netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), listener);
378 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
379 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
380 any(RemoteDeviceServices.class));
381 argument.getValue().capabilities().resolvedCapabilities()
382 .forEach(entry -> assertEquals("Builded 'AvailableCapability' schemas should match input capabilities.",
384 QName.create(entry.getCapability())).getName(), entry.getCapabilityOrigin().getName()));
388 public void testNetconfDeviceNotificationsModelNotPresentWithCapability() throws Exception {
389 final RemoteDeviceHandler facade = getFacade();
390 final NetconfDeviceCommunicator listener = getListener();
391 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
393 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
394 getSchemaRegistry(), getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
395 final NetconfDevice device = new NetconfDeviceBuilder()
396 .setSchemaResourcesDTO(schemaResourcesDTO)
397 .setGlobalProcessingExecutor(getExecutor())
399 .setSalFacade(facade)
400 .setBaseSchemas(BASE_SCHEMAS)
402 final NetconfDevice netconfSpy = spy(device);
404 final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of(CapabilityURN.NOTIFICATION));
406 netconfSpy.onRemoteSessionUp(sessionCaps, listener);
408 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
409 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
410 any(RemoteDeviceServices.class));
412 List<String> notificationModulesName = Arrays.asList(
413 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
414 .$YangModuleInfoImpl.getInstance().getName().toString(),
415 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
416 .$YangModuleInfoImpl.getInstance().getName().toString());
418 final Set<AvailableCapability> resolvedCapabilities = argument.getValue().capabilities().resolvedCapabilities();
420 assertEquals(2, resolvedCapabilities.size());
421 assertTrue(resolvedCapabilities.stream().anyMatch(entry -> notificationModulesName
422 .contains(entry.getCapability())));
426 public void testNetconfDeviceNotificationsCapabilityIsNotPresent() throws Exception {
427 final RemoteDeviceHandler facade = getFacade();
428 final NetconfDeviceCommunicator listener = getListener();
429 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
431 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
432 getSchemaRegistry(), getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
433 final NetconfDevice device = new NetconfDeviceBuilder()
434 .setSchemaResourcesDTO(schemaResourcesDTO)
435 .setGlobalProcessingExecutor(getExecutor())
437 .setSalFacade(facade)
438 .setBaseSchemas(BASE_SCHEMAS)
440 final NetconfDevice netconfSpy = spy(device);
442 final NetconfSessionPreferences sessionCaps = getSessionCaps(false,
443 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
445 netconfSpy.onRemoteSessionUp(sessionCaps, listener);
447 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
448 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
449 any(RemoteDeviceServices.class));
450 final NetconfDeviceCapabilities netconfDeviceCaps = argument.getValue().capabilities();
452 List<String> notificationModulesName = List.of(
453 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
454 .$YangModuleInfoImpl.getInstance().getName().toString(),
455 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
456 .$YangModuleInfoImpl.getInstance().getName().toString());
458 assertFalse(netconfDeviceCaps.resolvedCapabilities().stream()
459 .anyMatch(entry -> notificationModulesName.contains(entry.getCapability())));
463 public void testNetconfDeviceNotificationsModelIsPresent() throws Exception {
464 final RemoteDeviceHandler facade = getFacade();
465 final NetconfDeviceCommunicator listener = getListener();
466 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
468 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
469 getSchemaRegistry(), getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
470 final NetconfDevice device = new NetconfDeviceBuilder()
471 .setSchemaResourcesDTO(schemaResourcesDTO)
472 .setGlobalProcessingExecutor(getExecutor())
474 .setSalFacade(facade)
475 .setBaseSchemas(BASE_SCHEMAS)
477 final NetconfDevice netconfSpy = spy(device);
479 final NetconfSessionPreferences sessionCaps = getSessionCaps(false, Collections.emptyList());
481 final Map<QName, CapabilityOrigin> moduleBasedCaps = new HashMap<>();
482 moduleBasedCaps.put(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
483 .$YangModuleInfoImpl.getInstance().getName(),
484 CapabilityOrigin.DeviceAdvertised);
485 moduleBasedCaps.put(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
486 .$YangModuleInfoImpl.getInstance().getName(),
487 CapabilityOrigin.DeviceAdvertised);
490 netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), listener);
492 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
493 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
494 any(RemoteDeviceServices.class));
495 final Set<AvailableCapability> resolvedCapabilities = argument.getValue().capabilities().resolvedCapabilities();
497 List<String> notificationModulesName = List.of(
498 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
499 .$YangModuleInfoImpl.getInstance().getName().toString(),
500 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
501 .$YangModuleInfoImpl.getInstance().getName().toString());
503 assertEquals(2, resolvedCapabilities.size());
504 assertTrue(resolvedCapabilities.stream().anyMatch(entry -> notificationModulesName
505 .contains(entry.getCapability())));
508 private static EffectiveModelContextFactory getSchemaFactory() throws Exception {
509 final EffectiveModelContextFactory schemaFactory = mockClass(EffectiveModelContextFactory.class);
510 doReturn(Futures.immediateFuture(SCHEMA_CONTEXT))
511 .when(schemaFactory).createEffectiveModelContext(anyCollection());
512 return schemaFactory;
515 private static RemoteDeviceHandler getFacade() throws Exception {
516 final RemoteDeviceHandler remoteDeviceHandler = mockCloseableClass(RemoteDeviceHandler.class);
517 doNothing().when(remoteDeviceHandler).onDeviceConnected(
518 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
519 doNothing().when(remoteDeviceHandler).onDeviceDisconnected();
520 doNothing().when(remoteDeviceHandler).onNotification(any(DOMNotification.class));
521 return remoteDeviceHandler;
524 private static <T extends AutoCloseable> T mockCloseableClass(final Class<T> remoteDeviceHandlerClass)
526 final T mock = mockClass(remoteDeviceHandlerClass);
527 doNothing().when(mock).close();
531 private static <T> T mockClass(final Class<T> remoteDeviceHandlerClass) {
532 final T mock = mock(remoteDeviceHandlerClass);
533 doReturn(remoteDeviceHandlerClass.getSimpleName()).when(mock).toString();
537 public RemoteDeviceId getId() {
538 return new RemoteDeviceId("test-D", InetSocketAddress.createUnresolved("localhost", 22));
541 public ListeningExecutorService getExecutor() {
542 return MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
545 public NetconfSessionPreferences getSessionCaps(final boolean addMonitor,
546 final Collection<String> additionalCapabilities) {
547 final var capabilities = new ArrayList<String>();
548 capabilities.add(CapabilityURN.BASE);
549 capabilities.add(CapabilityURN.BASE_1_1);
551 capabilities.add(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING.getNamespace().toString());
553 capabilities.addAll(additionalCapabilities);
554 return NetconfSessionPreferences.fromStrings(capabilities);
557 public NetconfDeviceCommunicator getListener() throws Exception {
558 final NetconfDeviceCommunicator remoteDeviceCommunicator = mockCloseableClass(NetconfDeviceCommunicator.class);
559 // doReturn(Futures.immediateFuture(rpcResult))
560 // .when(remoteDeviceCommunicator).sendRequest(any(NetconfMessage.class), any(QName.class));
561 return remoteDeviceCommunicator;