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.Sets;
29 import com.google.common.util.concurrent.Futures;
30 import com.google.common.util.concurrent.MoreExecutors;
31 import com.google.common.util.concurrent.SettableFuture;
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.BeforeClass;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 import org.mockito.ArgumentCaptor;
43 import org.mockito.Mock;
44 import org.mockito.junit.MockitoJUnitRunner;
45 import org.opendaylight.mdsal.dom.api.DOMNotification;
46 import org.opendaylight.netconf.api.CapabilityURN;
47 import org.opendaylight.netconf.api.messages.NetconfMessage;
48 import org.opendaylight.netconf.api.xml.XmlUtil;
49 import org.opendaylight.netconf.client.mdsal.NetconfDevice.EmptySchemaContextException;
50 import org.opendaylight.netconf.client.mdsal.api.NetconfDeviceSchemasResolver;
51 import org.opendaylight.netconf.client.mdsal.api.NetconfSessionPreferences;
52 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceHandler;
53 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
54 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.connection.oper.available.capabilities.AvailableCapability;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.connection.oper.available.capabilities.AvailableCapability.CapabilityOrigin;
58 import org.opendaylight.yangtools.concepts.Registration;
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.api.source.SourceIdentifier;
63 import org.opendaylight.yangtools.yang.model.api.source.YangTextSource;
64 import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
65 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
66 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
67 import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
68 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
70 @RunWith(MockitoJUnitRunner.StrictStubs.class)
71 public class NetconfDeviceTest extends AbstractTestModelTest {
72 public static final String TEST_NAMESPACE = "test:namespace";
73 public static final String TEST_MODULE = "test-module";
74 public static final String TEST_REVISION = "2013-07-22";
75 public static final SourceIdentifier TEST_SID = new SourceIdentifier(TEST_MODULE, TEST_REVISION);
76 public static final String TEST_CAPABILITY =
77 TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION;
79 public static final SourceIdentifier TEST_SID2 = new SourceIdentifier(TEST_MODULE + "2", TEST_REVISION);
80 public static final String TEST_CAPABILITY2 =
81 TEST_NAMESPACE + "?module=" + TEST_MODULE + "2" + "&revision=" + TEST_REVISION;
83 private static final NetconfDeviceSchemasResolver STATE_SCHEMAS_RESOLVER =
84 (deviceRpc, remoteSessionCapabilities, id, schemaContext) -> NetconfStateSchemas.EMPTY;
86 private static NetconfMessage NOTIFICATION;
89 private SchemaSourceRegistry schemaRegistry;
92 public static final void setupNotification() throws Exception {
93 NOTIFICATION = new NetconfMessage(XmlUtil.readXmlToDocument(
94 NetconfDeviceTest.class.getResourceAsStream("/notification-payload.xml")));
98 public void testNetconfDeviceFlawedModelFailedResolution() throws Exception {
99 final RemoteDeviceHandler facade = getFacade();
100 final NetconfDeviceCommunicator listener = getListener();
102 final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
103 final SchemaRepository schemaRepository = getSchemaRepository();
105 final SchemaResolutionException schemaResolutionException =
106 new SchemaResolutionException("fail first", TEST_SID, new Throwable("YangTools parser fail"));
107 doAnswer(invocation -> {
108 if (((Collection<?>) invocation.getArguments()[0]).size() == 2) {
109 return Futures.immediateFailedFuture(schemaResolutionException);
111 return Futures.immediateFuture(SCHEMA_CONTEXT);
113 }).when(schemaFactory).createEffectiveModelContext(anyCollection());
115 final NetconfDeviceSchemasResolver stateSchemasResolver = (deviceRpc, remoteSessionCapabilities, id,
117 final Module first = SCHEMA_CONTEXT.getModules().iterator().next();
118 final QName qName = QName.create(first.getQNameModule(), first.getName());
119 final NetconfStateSchemas.RemoteYangSchema source1 = new NetconfStateSchemas.RemoteYangSchema(qName);
120 final NetconfStateSchemas.RemoteYangSchema source2 =
121 new NetconfStateSchemas.RemoteYangSchema(QName.create(first.getQNameModule(), "test-module2"));
122 return new NetconfStateSchemas(Sets.newHashSet(source1, source2));
125 doReturn(mock(Registration.class)).when(schemaRegistry).registerSchemaSource(any(), any());
126 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
127 .SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaFactory, stateSchemasResolver);
129 final NetconfDevice device = new NetconfDeviceBuilder()
130 .setReconnectOnSchemasChange(true)
131 .setSchemaResourcesDTO(schemaResourcesDTO)
132 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
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 new SourceIdentifier("test-module", "2013-07-22"), new Throwable());
157 doReturn(Futures.immediateFailedFuture(schemaResolutionException))
158 .when(schemaFactory).createEffectiveModelContext(anyCollection());
160 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
161 .SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaFactory, STATE_SCHEMAS_RESOLVER);
162 final NetconfDevice device = new NetconfDeviceBuilder()
163 .setReconnectOnSchemasChange(true)
164 .setSchemaResourcesDTO(schemaResourcesDTO)
165 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
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 final var captor = ArgumentCaptor.forClass(Throwable.class);
176 verify(facade, timeout(5000)).onDeviceFailed(captor.capture());
177 assertThat(captor.getValue(), instanceOf(EmptySchemaContextException.class));
179 verify(listener, timeout(5000)).close();
180 verify(schemaFactory, times(1)).createEffectiveModelContext(anyCollection());
184 public void testNetconfDeviceMissingSource() throws Exception {
185 final RemoteDeviceHandler facade = getFacade();
186 final NetconfDeviceCommunicator listener = getListener();
188 final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
189 final SchemaRepository schemaRepository = getSchemaRepository();
191 // Make fallback attempt to fail due to empty resolved sources
192 final MissingSchemaSourceException schemaResolutionException =
193 new MissingSchemaSourceException(TEST_SID, "fail first");
194 doReturn(Futures.immediateFailedFuture(schemaResolutionException))
195 .when(schemaRepository).getSchemaSource(eq(TEST_SID), eq(YangTextSource.class));
196 doAnswer(invocation -> {
197 if (invocation.getArgument(0, Collection.class).size() == 2) {
198 return Futures.immediateFailedFuture(schemaResolutionException);
200 return Futures.immediateFuture(SCHEMA_CONTEXT);
202 }).when(schemaFactory).createEffectiveModelContext(anyCollection());
204 final NetconfDeviceSchemasResolver stateSchemasResolver = (deviceRpc, remoteSessionCapabilities, id,
206 final Module first = SCHEMA_CONTEXT.getModules().iterator().next();
207 final QName qName = QName.create(first.getQNameModule(), first.getName());
208 final NetconfStateSchemas.RemoteYangSchema source1 = new NetconfStateSchemas.RemoteYangSchema(qName);
209 final NetconfStateSchemas.RemoteYangSchema source2 =
210 new NetconfStateSchemas.RemoteYangSchema(QName.create(first.getQNameModule(), "test-module2"));
211 return new NetconfStateSchemas(Sets.newHashSet(source1, source2));
214 doReturn(mock(Registration.class)).when(schemaRegistry).registerSchemaSource(any(), any());
215 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
216 .SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaFactory, stateSchemasResolver);
218 final NetconfDevice device = new NetconfDeviceBuilder()
219 .setReconnectOnSchemasChange(true)
220 .setSchemaResourcesDTO(schemaResourcesDTO)
221 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
222 .setBaseSchemas(BASE_SCHEMAS)
224 .setSalFacade(facade)
226 // Monitoring supported
227 final NetconfSessionPreferences sessionCaps =
228 getSessionCaps(true, List.of(TEST_CAPABILITY, TEST_CAPABILITY2));
229 device.onRemoteSessionUp(sessionCaps, listener);
231 verify(facade, timeout(5000)).onDeviceConnected(any(NetconfDeviceSchema.class),
232 any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
233 verify(schemaFactory, times(1)).createEffectiveModelContext(anyCollection());
236 private static SchemaRepository getSchemaRepository() {
237 final SchemaRepository mock = mock(SchemaRepository.class);
238 final YangTextSource mockRep = mock(YangTextSource.class);
239 doReturn(Futures.immediateFuture(mockRep))
240 .when(mock).getSchemaSource(any(SourceIdentifier.class), eq(YangTextSource.class));
245 public void testNotificationBeforeSchema() throws Exception {
246 final RemoteDeviceHandler facade = getFacade();
247 final NetconfDeviceCommunicator listener = getListener();
248 final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
249 final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
250 doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
251 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
252 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
253 final NetconfDevice device = new NetconfDeviceBuilder()
254 .setReconnectOnSchemasChange(true)
255 .setSchemaResourcesDTO(schemaResourcesDTO)
256 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
258 .setSalFacade(facade)
259 .setBaseSchemas(BASE_SCHEMAS)
262 final NetconfSessionPreferences sessionCaps = getSessionCaps(true, List.of(TEST_CAPABILITY));
263 device.onRemoteSessionUp(sessionCaps, listener);
265 device.onNotification(NOTIFICATION);
266 device.onNotification(NOTIFICATION);
267 verify(facade, times(0)).onNotification(any(DOMNotification.class));
269 verify(facade, times(0)).onNotification(any(DOMNotification.class));
270 schemaFuture.set(NetconfToNotificationTest.getNotificationSchemaContext(getClass(), false));
271 verify(facade, timeout(10000).times(2)).onNotification(any(DOMNotification.class));
273 device.onNotification(NOTIFICATION);
274 verify(facade, timeout(10000).times(3)).onNotification(any(DOMNotification.class));
278 public void testNetconfDeviceReconnect() throws Exception {
279 final RemoteDeviceHandler facade = getFacade();
280 final NetconfDeviceCommunicator listener = getListener();
282 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
284 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
285 schemaRegistry, getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
286 final NetconfDevice device = new NetconfDeviceBuilder()
287 .setReconnectOnSchemasChange(true)
288 .setSchemaResourcesDTO(schemaResourcesDTO)
289 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
291 .setSalFacade(facade)
292 .setBaseSchemas(BASE_SCHEMAS)
294 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
295 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
296 device.onRemoteSessionUp(sessionCaps, listener);
298 verify(schemaContextProviderFactory, timeout(5000)).createEffectiveModelContext(anyCollection());
299 verify(facade, timeout(5000)).onDeviceConnected(
300 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
302 device.onRemoteSessionDown();
303 verify(facade, timeout(5000)).onDeviceDisconnected();
305 device.onRemoteSessionUp(sessionCaps, listener);
307 verify(schemaContextProviderFactory, timeout(5000).times(2)).createEffectiveModelContext(anyCollection());
308 verify(facade, timeout(5000).times(2)).onDeviceConnected(
309 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
313 public void testNetconfDeviceDisconnectListenerCallCancellation() throws Exception {
314 final RemoteDeviceHandler facade = getFacade();
315 final NetconfDeviceCommunicator listener = getListener();
316 final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
317 final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
318 doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
319 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
320 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
321 final NetconfDevice device = new NetconfDeviceBuilder()
322 .setReconnectOnSchemasChange(true)
323 .setSchemaResourcesDTO(schemaResourcesDTO)
324 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
326 .setSalFacade(facade)
327 .setBaseSchemas(BASE_SCHEMAS)
329 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
330 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
331 //session up, start schema resolution
332 device.onRemoteSessionUp(sessionCaps, listener);
334 device.onRemoteSessionDown();
335 verify(facade, timeout(5000)).onDeviceDisconnected();
336 //complete schema setup
337 schemaFuture.set(SCHEMA_CONTEXT);
338 //facade.onDeviceDisconnected() was called, so facade.onDeviceConnected() shouldn't be called anymore
339 verify(facade, after(1000).never()).onDeviceConnected(any(), any(), any(RemoteDeviceServices.class));
343 public void testNetconfDeviceReconnectBeforeSchemaSetup() throws Exception {
344 final RemoteDeviceHandler facade = getFacade();
346 final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
347 final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
348 doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
350 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
351 schemaRegistry, getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
352 final NetconfDevice device = new NetconfDeviceBuilder()
353 .setReconnectOnSchemasChange(true)
354 .setSchemaResourcesDTO(schemaResourcesDTO)
355 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
357 .setSalFacade(facade)
358 .setBaseSchemas(BASE_SCHEMAS)
360 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
361 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
363 final NetconfDeviceCommunicator listener = getListener();
364 // session up, start schema resolution
365 device.onRemoteSessionUp(sessionCaps, listener);
367 device.onRemoteSessionDown();
368 verify(facade, timeout(5000)).onDeviceDisconnected();
369 // session back up, start another schema resolution
370 device.onRemoteSessionUp(sessionCaps, listener);
371 // complete schema setup
372 schemaFuture.set(SCHEMA_CONTEXT);
373 // schema setup performed twice
374 verify(schemaContextProviderFactory, timeout(5000).times(2)).createEffectiveModelContext(anyCollection());
375 // onDeviceConnected called once
376 verify(facade, timeout(5000)).onDeviceConnected(
377 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
381 public void testNetconfDeviceAvailableCapabilitiesBuilding() throws Exception {
382 final RemoteDeviceHandler facade = getFacade();
383 final NetconfDeviceCommunicator listener = getListener();
385 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
387 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
388 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
389 final NetconfDevice device = new NetconfDeviceBuilder()
390 .setReconnectOnSchemasChange(true)
391 .setSchemaResourcesDTO(schemaResourcesDTO)
392 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
394 .setSalFacade(facade)
395 .setBaseSchemas(BASE_SCHEMAS)
397 final NetconfDevice netconfSpy = spy(device);
399 final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
400 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
401 final Map<QName, CapabilityOrigin> moduleBasedCaps = new HashMap<>();
402 moduleBasedCaps.putAll(sessionCaps.moduleBasedCaps());
404 .put(QName.create("(test:qname:side:loading)test"), CapabilityOrigin.UserDefined);
406 netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), 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));
411 argument.getValue().capabilities().resolvedCapabilities()
412 .forEach(entry -> assertEquals("Builded 'AvailableCapability' schemas should match input capabilities.",
414 QName.create(entry.getCapability())).getName(), entry.getCapabilityOrigin().getName()));
418 public void testNetconfDeviceNotificationsModelNotPresentWithCapability() throws Exception {
419 final RemoteDeviceHandler facade = getFacade();
420 final NetconfDeviceCommunicator listener = getListener();
421 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
423 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
424 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
425 final NetconfDevice device = new NetconfDeviceBuilder()
426 .setSchemaResourcesDTO(schemaResourcesDTO)
427 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
429 .setSalFacade(facade)
430 .setBaseSchemas(BASE_SCHEMAS)
432 final NetconfDevice netconfSpy = spy(device);
434 final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of(CapabilityURN.NOTIFICATION));
436 netconfSpy.onRemoteSessionUp(sessionCaps, listener);
438 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
439 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
440 any(RemoteDeviceServices.class));
442 List<String> notificationModulesName = List.of(
443 org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
444 .YangModuleInfoImpl.getInstance().getName().toString(),
445 org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
446 .YangModuleInfoImpl.getInstance().getName().toString());
448 final Set<AvailableCapability> resolvedCapabilities = argument.getValue().capabilities().resolvedCapabilities();
450 assertEquals(2, resolvedCapabilities.size());
451 assertTrue(resolvedCapabilities.stream().anyMatch(entry -> notificationModulesName
452 .contains(entry.getCapability())));
456 public void testNetconfDeviceNotificationsCapabilityIsNotPresent() throws Exception {
457 final RemoteDeviceHandler facade = getFacade();
458 final NetconfDeviceCommunicator listener = getListener();
459 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
461 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
462 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
463 final NetconfDevice device = new NetconfDeviceBuilder()
464 .setSchemaResourcesDTO(schemaResourcesDTO)
465 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
467 .setSalFacade(facade)
468 .setBaseSchemas(BASE_SCHEMAS)
470 final NetconfDevice netconfSpy = spy(device);
472 final NetconfSessionPreferences sessionCaps = getSessionCaps(false,
473 List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
475 netconfSpy.onRemoteSessionUp(sessionCaps, listener);
477 final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
478 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
479 any(RemoteDeviceServices.class));
480 final NetconfDeviceCapabilities netconfDeviceCaps = argument.getValue().capabilities();
482 List<String> notificationModulesName = List.of(
483 org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
484 .YangModuleInfoImpl.getInstance().getName().toString(),
485 org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
486 .YangModuleInfoImpl.getInstance().getName().toString());
488 assertFalse(netconfDeviceCaps.resolvedCapabilities().stream()
489 .anyMatch(entry -> notificationModulesName.contains(entry.getCapability())));
493 public void testNetconfDeviceNotificationsModelIsPresent() throws Exception {
494 final RemoteDeviceHandler facade = getFacade();
495 final NetconfDeviceCommunicator listener = getListener();
496 final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
498 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
499 getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
500 final NetconfDevice device = new NetconfDeviceBuilder()
501 .setSchemaResourcesDTO(schemaResourcesDTO)
502 .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
504 .setSalFacade(facade)
505 .setBaseSchemas(BASE_SCHEMAS)
507 final NetconfDevice netconfSpy = spy(device);
509 final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of());
511 final var moduleBasedCaps = new HashMap<QName, CapabilityOrigin>();
512 moduleBasedCaps.put(org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
513 .YangModuleInfoImpl.getInstance().getName(),
514 CapabilityOrigin.DeviceAdvertised);
515 moduleBasedCaps.put(org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
516 .YangModuleInfoImpl.getInstance().getName(),
517 CapabilityOrigin.DeviceAdvertised);
520 netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), listener);
522 final var argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
523 verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
524 any(RemoteDeviceServices.class));
525 final Set<AvailableCapability> resolvedCapabilities = argument.getValue().capabilities().resolvedCapabilities();
527 final var notificationModulesName = List.of(
528 org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
529 .YangModuleInfoImpl.getInstance().getName().toString(),
530 org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
531 .YangModuleInfoImpl.getInstance().getName().toString());
533 assertEquals(2, resolvedCapabilities.size());
534 assertTrue(resolvedCapabilities.stream().anyMatch(entry -> notificationModulesName
535 .contains(entry.getCapability())));
538 private static EffectiveModelContextFactory getSchemaFactory() throws Exception {
539 final EffectiveModelContextFactory schemaFactory = mock(EffectiveModelContextFactory.class);
540 doReturn(Futures.immediateFuture(SCHEMA_CONTEXT))
541 .when(schemaFactory).createEffectiveModelContext(anyCollection());
542 return schemaFactory;
545 private static RemoteDeviceHandler getFacade() throws Exception {
546 final RemoteDeviceHandler remoteDeviceHandler = mockCloseableClass(RemoteDeviceHandler.class);
547 doNothing().when(remoteDeviceHandler).onDeviceConnected(
548 any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
549 doNothing().when(remoteDeviceHandler).onDeviceDisconnected();
550 doNothing().when(remoteDeviceHandler).onNotification(any(DOMNotification.class));
551 return remoteDeviceHandler;
554 private static <T extends AutoCloseable> T mockCloseableClass(final Class<T> remoteDeviceHandlerClass)
556 final T mock = mock(remoteDeviceHandlerClass);
557 doNothing().when(mock).close();
561 public RemoteDeviceId getId() {
562 return new RemoteDeviceId("test-D", InetSocketAddress.createUnresolved("localhost", 22));
565 public NetconfSessionPreferences getSessionCaps(final boolean addMonitor,
566 final Collection<String> additionalCapabilities) {
567 final var capabilities = new ArrayList<String>();
568 capabilities.add(CapabilityURN.BASE);
569 capabilities.add(CapabilityURN.BASE_1_1);
571 capabilities.add(NetconfState.QNAME.getNamespace().toString());
573 capabilities.addAll(additionalCapabilities);
574 return NetconfSessionPreferences.fromStrings(capabilities);
577 public NetconfDeviceCommunicator getListener() throws Exception {
578 return mockCloseableClass(NetconfDeviceCommunicator.class);