*/
package org.opendaylight.netconf.client.mdsal;
-import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyCollection;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.after;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import java.net.InetSocketAddress;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.jupiter.MockitoExtension;
import org.opendaylight.mdsal.dom.api.DOMNotification;
import org.opendaylight.netconf.api.CapabilityURN;
import org.opendaylight.netconf.api.messages.NetconfMessage;
import org.opendaylight.netconf.api.xml.XmlUtil;
import org.opendaylight.netconf.client.mdsal.NetconfDevice.EmptySchemaContextException;
-import org.opendaylight.netconf.client.mdsal.api.NetconfDeviceSchemasResolver;
+import org.opendaylight.netconf.client.mdsal.api.DeviceNetconfSchema;
+import org.opendaylight.netconf.client.mdsal.api.DeviceNetconfSchemaProvider;
import org.opendaylight.netconf.client.mdsal.api.NetconfSessionPreferences;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceHandler;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices;
+import org.opendaylight.netconf.client.mdsal.impl.DefaultDeviceNetconfSchemaProvider;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.connection.oper.available.capabilities.AvailableCapability;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.connection.oper.available.capabilities.AvailableCapability.CapabilityOrigin;
-import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240611.connection.oper.available.capabilities.AvailableCapability.CapabilityOrigin;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240611.connection.oper.available.capabilities.AvailableCapabilityBuilder;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
import org.opendaylight.yangtools.yang.model.api.source.YangTextSource;
import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
-import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
-@RunWith(MockitoJUnitRunner.StrictStubs.class)
-public class NetconfDeviceTest extends AbstractTestModelTest {
- public static final String TEST_NAMESPACE = "test:namespace";
- public static final String TEST_MODULE = "test-module";
- public static final String TEST_REVISION = "2013-07-22";
- public static final SourceIdentifier TEST_SID = new SourceIdentifier(TEST_MODULE, TEST_REVISION);
- public static final String TEST_CAPABILITY =
+@ExtendWith(MockitoExtension.class)
+class NetconfDeviceTest extends AbstractTestModelTest {
+ private static final String TEST_NAMESPACE = "test:namespace";
+ private static final String TEST_MODULE = "test-module";
+ private static final String TEST_REVISION = "2013-07-22";
+ private static final SourceIdentifier TEST_SID = new SourceIdentifier(TEST_MODULE, TEST_REVISION);
+ private static final String TEST_CAPABILITY =
TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION;
- public static final SourceIdentifier TEST_SID2 = new SourceIdentifier(TEST_MODULE + "2", TEST_REVISION);
- public static final String TEST_CAPABILITY2 =
- TEST_NAMESPACE + "?module=" + TEST_MODULE + "2" + "&revision=" + TEST_REVISION;
-
- private static final NetconfDeviceSchemasResolver STATE_SCHEMAS_RESOLVER =
- (deviceRpc, remoteSessionCapabilities, id, schemaContext) -> NetconfStateSchemas.EMPTY;
-
private static NetconfMessage NOTIFICATION;
@Mock
private SchemaSourceRegistry schemaRegistry;
+ @Mock
+ private DeviceNetconfSchemaProvider schemaProvider;
+ @Mock
+ private RemoteDeviceHandler facade;
+ @Mock
+ private NetconfDeviceCommunicator listener;
+ @Mock
+ private EffectiveModelContextFactory schemaFactory;
+ @Mock
+ private DeviceNetconfSchemaProvider deviceSchemaProvider;
- @BeforeClass
- public static final void setupNotification() throws Exception {
+ @BeforeAll
+ static void setupNotification() throws Exception {
NOTIFICATION = new NetconfMessage(XmlUtil.readXmlToDocument(
NetconfDeviceTest.class.getResourceAsStream("/notification-payload.xml")));
}
@Test
- public void testNetconfDeviceFlawedModelFailedResolution() throws Exception {
- final RemoteDeviceHandler facade = getFacade();
- final NetconfDeviceCommunicator listener = getListener();
-
- final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
- final SchemaRepository schemaRepository = getSchemaRepository();
-
- final SchemaResolutionException schemaResolutionException =
- new SchemaResolutionException("fail first", TEST_SID, new Throwable("YangTools parser fail"));
- doAnswer(invocation -> {
- if (((Collection<?>) invocation.getArguments()[0]).size() == 2) {
- return Futures.immediateFailedFuture(schemaResolutionException);
- } else {
- return Futures.immediateFuture(SCHEMA_CONTEXT);
- }
- }).when(schemaFactory).createEffectiveModelContext(anyCollection());
-
- final NetconfDeviceSchemasResolver stateSchemasResolver = (deviceRpc, remoteSessionCapabilities, id,
- schemaContext) -> {
- final Module first = SCHEMA_CONTEXT.getModules().iterator().next();
- final QName qName = QName.create(first.getQNameModule(), first.getName());
- final NetconfStateSchemas.RemoteYangSchema source1 = new NetconfStateSchemas.RemoteYangSchema(qName);
- final NetconfStateSchemas.RemoteYangSchema source2 =
- new NetconfStateSchemas.RemoteYangSchema(QName.create(first.getQNameModule(), "test-module2"));
- return new NetconfStateSchemas(Sets.newHashSet(source1, source2));
- };
-
- doReturn(mock(Registration.class)).when(schemaRegistry).registerSchemaSource(any(), any());
- final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
- .SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaFactory, stateSchemasResolver);
-
- final NetconfDevice device = new NetconfDeviceBuilder()
- .setReconnectOnSchemasChange(true)
- .setSchemaResourcesDTO(schemaResourcesDTO)
- .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
- .setId(getId())
- .setSalFacade(facade)
- .setBaseSchemas(BASE_SCHEMAS)
- .build();
- // Monitoring supported
- final NetconfSessionPreferences sessionCaps = getSessionCaps(true, List.of(TEST_CAPABILITY, TEST_CAPABILITY2));
- device.onRemoteSessionUp(sessionCaps, listener);
-
- verify(facade, timeout(5000)).onDeviceConnected(any(NetconfDeviceSchema.class),
- any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
- verify(schemaFactory, times(2)).createEffectiveModelContext(anyCollection());
- }
-
- @Test
- public void testNetconfDeviceFailFirstSchemaFailSecondEmpty() throws Exception {
- final RemoteDeviceHandler facade = getFacade();
- final NetconfDeviceCommunicator listener = getListener();
-
- final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
- final SchemaRepository schemaRepository = getSchemaRepository();
-
+ void testNetconfDeviceFailFirstSchemaFailSecondEmpty() {
// Make fallback attempt to fail due to empty resolved sources
- final SchemaResolutionException schemaResolutionException = new SchemaResolutionException("fail first",
+ final var schemaResolutionException = new SchemaResolutionException("fail first",
new SourceIdentifier("test-module", "2013-07-22"), new Throwable());
doReturn(Futures.immediateFailedFuture(schemaResolutionException))
.when(schemaFactory).createEffectiveModelContext(anyCollection());
- final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
- .SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaFactory, STATE_SCHEMAS_RESOLVER);
- final NetconfDevice device = new NetconfDeviceBuilder()
- .setReconnectOnSchemasChange(true)
- .setSchemaResourcesDTO(schemaResourcesDTO)
- .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
- .setId(getId())
- .setSalFacade(facade)
- .setBaseSchemas(BASE_SCHEMAS)
- .build();
+ final var device = new NetconfDeviceBuilder()
+ .setReconnectOnSchemasChange(true)
+ .setDeviceSchemaProvider(mockDeviceNetconfSchemaProvider(getSchemaRepository(), schemaFactory))
+ .setProcessingExecutor(MoreExecutors.directExecutor())
+ .setId(getId())
+ .setSalFacade(facade)
+ .setBaseSchemaProvider(BASE_SCHEMAS)
+ .build();
// Monitoring not supported
- final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of(TEST_CAPABILITY));
- device.onRemoteSessionUp(sessionCaps, listener);
+ device.onRemoteSessionUp(getSessionCaps(false, TEST_CAPABILITY), listener);
final var captor = ArgumentCaptor.forClass(Throwable.class);
verify(facade, timeout(5000)).onDeviceFailed(captor.capture());
- assertThat(captor.getValue(), instanceOf(EmptySchemaContextException.class));
+ assertInstanceOf(EmptySchemaContextException.class, captor.getValue());
verify(listener, timeout(5000)).close();
verify(schemaFactory, times(1)).createEffectiveModelContext(anyCollection());
}
- @Test
- public void testNetconfDeviceMissingSource() throws Exception {
- final RemoteDeviceHandler facade = getFacade();
- final NetconfDeviceCommunicator listener = getListener();
-
- final EffectiveModelContextFactory schemaFactory = getSchemaFactory();
- final SchemaRepository schemaRepository = getSchemaRepository();
-
- // Make fallback attempt to fail due to empty resolved sources
- final MissingSchemaSourceException schemaResolutionException =
- new MissingSchemaSourceException(TEST_SID, "fail first");
- doReturn(Futures.immediateFailedFuture(schemaResolutionException))
- .when(schemaRepository).getSchemaSource(eq(TEST_SID), eq(YangTextSource.class));
- doAnswer(invocation -> {
- if (invocation.getArgument(0, Collection.class).size() == 2) {
- return Futures.immediateFailedFuture(schemaResolutionException);
- } else {
- return Futures.immediateFuture(SCHEMA_CONTEXT);
- }
- }).when(schemaFactory).createEffectiveModelContext(anyCollection());
-
- final NetconfDeviceSchemasResolver stateSchemasResolver = (deviceRpc, remoteSessionCapabilities, id,
- schemaContext) -> {
- final Module first = SCHEMA_CONTEXT.getModules().iterator().next();
- final QName qName = QName.create(first.getQNameModule(), first.getName());
- final NetconfStateSchemas.RemoteYangSchema source1 = new NetconfStateSchemas.RemoteYangSchema(qName);
- final NetconfStateSchemas.RemoteYangSchema source2 =
- new NetconfStateSchemas.RemoteYangSchema(QName.create(first.getQNameModule(), "test-module2"));
- return new NetconfStateSchemas(Sets.newHashSet(source1, source2));
- };
-
- doReturn(mock(Registration.class)).when(schemaRegistry).registerSchemaSource(any(), any());
- final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice
- .SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaFactory, stateSchemasResolver);
-
- final NetconfDevice device = new NetconfDeviceBuilder()
- .setReconnectOnSchemasChange(true)
- .setSchemaResourcesDTO(schemaResourcesDTO)
- .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
- .setBaseSchemas(BASE_SCHEMAS)
- .setId(getId())
- .setSalFacade(facade)
- .build();
- // Monitoring supported
- final NetconfSessionPreferences sessionCaps =
- getSessionCaps(true, List.of(TEST_CAPABILITY, TEST_CAPABILITY2));
- device.onRemoteSessionUp(sessionCaps, listener);
-
- verify(facade, timeout(5000)).onDeviceConnected(any(NetconfDeviceSchema.class),
- any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
- verify(schemaFactory, times(1)).createEffectiveModelContext(anyCollection());
- }
-
private static SchemaRepository getSchemaRepository() {
- final SchemaRepository mock = mock(SchemaRepository.class);
- final YangTextSource mockRep = mock(YangTextSource.class);
+ final var mock = mock(SchemaRepository.class);
+ final var mockRep = mock(YangTextSource.class);
doReturn(Futures.immediateFuture(mockRep))
.when(mock).getSchemaSource(any(SourceIdentifier.class), eq(YangTextSource.class));
return mock;
}
@Test
- public void testNotificationBeforeSchema() throws Exception {
- final RemoteDeviceHandler facade = getFacade();
- final NetconfDeviceCommunicator listener = getListener();
- final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
- final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
- doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
- final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
- getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
- final NetconfDevice device = new NetconfDeviceBuilder()
- .setReconnectOnSchemasChange(true)
- .setSchemaResourcesDTO(schemaResourcesDTO)
- .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
- .setId(getId())
- .setSalFacade(facade)
- .setBaseSchemas(BASE_SCHEMAS)
- .build();
-
- final NetconfSessionPreferences sessionCaps = getSessionCaps(true, List.of(TEST_CAPABILITY));
+ void testNotificationBeforeSchema() {
+ final var remoteDeviceHandler = mockRemoteDeviceHandler();
+ doNothing().when(remoteDeviceHandler).onNotification(any(DOMNotification.class));
+ final var schemaFuture = SettableFuture.<DeviceNetconfSchema>create();
+ doReturn(schemaFuture).when(deviceSchemaProvider).deviceNetconfSchemaFor(any(), any(), any(), any(), any());
+
+ final var device = new NetconfDeviceBuilder()
+ .setReconnectOnSchemasChange(true)
+ .setDeviceSchemaProvider(deviceSchemaProvider)
+ .setProcessingExecutor(MoreExecutors.directExecutor())
+ .setId(getId())
+ .setSalFacade(remoteDeviceHandler)
+ .setBaseSchemaProvider(BASE_SCHEMAS)
+ .build();
+
+ final var sessionCaps = getSessionCaps(true, TEST_CAPABILITY);
device.onRemoteSessionUp(sessionCaps, listener);
device.onNotification(NOTIFICATION);
device.onNotification(NOTIFICATION);
- verify(facade, times(0)).onNotification(any(DOMNotification.class));
+ verify(remoteDeviceHandler, times(0)).onNotification(any(DOMNotification.class));
+
+ // Now enable schema
+ schemaFuture.set(new DeviceNetconfSchema(NetconfDeviceCapabilities.empty(),
+ NetconfToNotificationTest.getNotificationSchemaContext(NetconfDeviceTest.class, false)));
- verify(facade, times(0)).onNotification(any(DOMNotification.class));
- schemaFuture.set(NetconfToNotificationTest.getNotificationSchemaContext(getClass(), false));
- verify(facade, timeout(10000).times(2)).onNotification(any(DOMNotification.class));
+ verify(remoteDeviceHandler, timeout(10000).times(2))
+ .onNotification(any(DOMNotification.class));
device.onNotification(NOTIFICATION);
- verify(facade, timeout(10000).times(3)).onNotification(any(DOMNotification.class));
+ verify(remoteDeviceHandler, times(3)).onNotification(any(DOMNotification.class));
+ }
+
+ private RemoteDeviceHandler mockRemoteDeviceHandler() {
+ doNothing().when(facade).onDeviceConnected(
+ any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
+ return facade;
}
@Test
- public void testNetconfDeviceReconnect() throws Exception {
- final RemoteDeviceHandler facade = getFacade();
- final NetconfDeviceCommunicator listener = getListener();
-
- final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
-
- final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
- schemaRegistry, getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
- final NetconfDevice device = new NetconfDeviceBuilder()
- .setReconnectOnSchemasChange(true)
- .setSchemaResourcesDTO(schemaResourcesDTO)
- .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
- .setId(getId())
- .setSalFacade(facade)
- .setBaseSchemas(BASE_SCHEMAS)
- .build();
- final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
- List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
+ void testNetconfDeviceReconnect() {
+ doReturn(RpcResultBuilder.failed().buildFuture()).when(listener).sendRequest(any());
+
+ final var device = new NetconfDeviceBuilder()
+ .setReconnectOnSchemasChange(true)
+ .setDeviceSchemaProvider(mockDeviceNetconfSchemaProvider())
+ .setProcessingExecutor(MoreExecutors.directExecutor())
+ .setId(getId())
+ .setSalFacade(facade)
+ .setBaseSchemaProvider(BASE_SCHEMAS)
+ .build();
+ final var sessionCaps = getSessionCaps(true,
+ TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION);
device.onRemoteSessionUp(sessionCaps, listener);
- verify(schemaContextProviderFactory, timeout(5000)).createEffectiveModelContext(anyCollection());
verify(facade, timeout(5000)).onDeviceConnected(
any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
device.onRemoteSessionUp(sessionCaps, listener);
- verify(schemaContextProviderFactory, timeout(5000).times(2)).createEffectiveModelContext(anyCollection());
verify(facade, timeout(5000).times(2)).onDeviceConnected(
any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
}
@Test
- public void testNetconfDeviceDisconnectListenerCallCancellation() throws Exception {
- final RemoteDeviceHandler facade = getFacade();
- final NetconfDeviceCommunicator listener = getListener();
- final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
- final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
- doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
- final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
- getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
- final NetconfDevice device = new NetconfDeviceBuilder()
- .setReconnectOnSchemasChange(true)
- .setSchemaResourcesDTO(schemaResourcesDTO)
- .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
- .setId(getId())
- .setSalFacade(facade)
- .setBaseSchemas(BASE_SCHEMAS)
- .build();
- final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
- List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
+ void testNetconfDeviceDisconnectListenerCallCancellation() {
+ doNothing().when(facade).onDeviceDisconnected();
+ final var schemaFuture = SettableFuture.<DeviceNetconfSchema>create();
+ doReturn(schemaFuture).when(schemaProvider).deviceNetconfSchemaFor(any(), any(), any(), any(), any());
+
+ final var device = new NetconfDeviceBuilder()
+ .setReconnectOnSchemasChange(true)
+ .setDeviceSchemaProvider(schemaProvider)
+ .setProcessingExecutor(MoreExecutors.directExecutor())
+ .setId(getId())
+ .setSalFacade(facade)
+ .setBaseSchemaProvider(BASE_SCHEMAS)
+ .build();
//session up, start schema resolution
- device.onRemoteSessionUp(sessionCaps, listener);
+ device.onRemoteSessionUp(getSessionCaps(true,
+ TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION),
+ listener);
//session closed
device.onRemoteSessionDown();
verify(facade, timeout(5000)).onDeviceDisconnected();
//complete schema setup
- schemaFuture.set(SCHEMA_CONTEXT);
+ schemaFuture.set(new DeviceNetconfSchema(NetconfDeviceCapabilities.empty(), SCHEMA_CONTEXT));
//facade.onDeviceDisconnected() was called, so facade.onDeviceConnected() shouldn't be called anymore
verify(facade, after(1000).never()).onDeviceConnected(any(), any(), any(RemoteDeviceServices.class));
}
@Test
- public void testNetconfDeviceReconnectBeforeSchemaSetup() throws Exception {
- final RemoteDeviceHandler facade = getFacade();
+ void testNetconfDeviceReconnectBeforeSchemaSetup() {
+ final var schemaFuture = SettableFuture.<EffectiveModelContext>create();
+ doReturn(schemaFuture).when(schemaFactory).createEffectiveModelContext(anyCollection());
- final EffectiveModelContextFactory schemaContextProviderFactory = mock(EffectiveModelContextFactory.class);
- final SettableFuture<SchemaContext> schemaFuture = SettableFuture.create();
- doReturn(schemaFuture).when(schemaContextProviderFactory).createEffectiveModelContext(anyCollection());
+ doReturn(RpcResultBuilder.failed().buildFuture()).when(listener).sendRequest(any());
- final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(
- schemaRegistry, getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
- final NetconfDevice device = new NetconfDeviceBuilder()
+ final var device = new NetconfDeviceBuilder()
.setReconnectOnSchemasChange(true)
- .setSchemaResourcesDTO(schemaResourcesDTO)
- .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
+ .setDeviceSchemaProvider(mockDeviceNetconfSchemaProvider(getSchemaRepository(),
+ schemaFactory))
+ .setProcessingExecutor(MoreExecutors.directExecutor())
.setId(getId())
.setSalFacade(facade)
- .setBaseSchemas(BASE_SCHEMAS)
+ .setBaseSchemaProvider(BASE_SCHEMAS)
.build();
- final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
- List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
+ final var sessionCaps = getSessionCaps(true,
+ TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION);
- final NetconfDeviceCommunicator listener = getListener();
// session up, start schema resolution
device.onRemoteSessionUp(sessionCaps, listener);
// session down
// complete schema setup
schemaFuture.set(SCHEMA_CONTEXT);
// schema setup performed twice
- verify(schemaContextProviderFactory, timeout(5000).times(2)).createEffectiveModelContext(anyCollection());
+ verify(schemaFactory, timeout(5000).times(2)).createEffectiveModelContext(anyCollection());
// onDeviceConnected called once
verify(facade, timeout(5000)).onDeviceConnected(
any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
}
@Test
- public void testNetconfDeviceAvailableCapabilitiesBuilding() throws Exception {
- final RemoteDeviceHandler facade = getFacade();
- final NetconfDeviceCommunicator listener = getListener();
-
- final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
-
- final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
- getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
- final NetconfDevice device = new NetconfDeviceBuilder()
- .setReconnectOnSchemasChange(true)
- .setSchemaResourcesDTO(schemaResourcesDTO)
- .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
- .setId(getId())
- .setSalFacade(facade)
- .setBaseSchemas(BASE_SCHEMAS)
- .build();
- final NetconfDevice netconfSpy = spy(device);
-
- final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
- List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
- final Map<QName, CapabilityOrigin> moduleBasedCaps = new HashMap<>();
+ void testNetconfDeviceAvailableCapabilitiesBuilding() {
+ doReturn(RpcResultBuilder.failed().buildFuture()).when(listener).sendRequest(any());
+
+ final var netconfSpy = spy(new NetconfDeviceBuilder()
+ .setReconnectOnSchemasChange(true)
+ .setDeviceSchemaProvider(mockDeviceNetconfSchemaProvider())
+ .setProcessingExecutor(MoreExecutors.directExecutor())
+ .setId(getId())
+ .setSalFacade(facade)
+ .setBaseSchemaProvider(BASE_SCHEMAS)
+ .build());
+
+ final var sessionCaps = getSessionCaps(true,
+ TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION);
+ final var moduleBasedCaps = new HashMap<QName, CapabilityOrigin>();
moduleBasedCaps.putAll(sessionCaps.moduleBasedCaps());
- moduleBasedCaps
- .put(QName.create("(test:qname:side:loading)test"), CapabilityOrigin.UserDefined);
+ moduleBasedCaps.put(QName.create("(test:qname:side:loading)test"), CapabilityOrigin.UserDefined);
netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), listener);
- final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
- verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
- any(RemoteDeviceServices.class));
- argument.getValue().capabilities().resolvedCapabilities()
- .forEach(entry -> assertEquals("Builded 'AvailableCapability' schemas should match input capabilities.",
- moduleBasedCaps.get(
- QName.create(entry.getCapability())).getName(), entry.getCapabilityOrigin().getName()));
+ final var argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
+ verify(facade, timeout(5000)).onDeviceConnected(argument.capture(),
+ any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
+
+ assertEquals(Set.of(
+ new AvailableCapabilityBuilder()
+ .setCapability("(test:namespace?revision=2013-07-22)test-module")
+ .setCapabilityOrigin(CapabilityOrigin.DeviceAdvertised)
+ .build(),
+ new AvailableCapabilityBuilder()
+ .setCapability("(test:qname:side:loading)test")
+ .setCapabilityOrigin(CapabilityOrigin.UserDefined)
+ .build()), argument.getValue().capabilities().resolvedCapabilities());
}
@Test
- public void testNetconfDeviceNotificationsModelNotPresentWithCapability() throws Exception {
- final RemoteDeviceHandler facade = getFacade();
- final NetconfDeviceCommunicator listener = getListener();
- final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
-
- final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
- getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
- final NetconfDevice device = new NetconfDeviceBuilder()
- .setSchemaResourcesDTO(schemaResourcesDTO)
- .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
- .setId(getId())
- .setSalFacade(facade)
- .setBaseSchemas(BASE_SCHEMAS)
- .build();
- final NetconfDevice netconfSpy = spy(device);
-
- final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of(CapabilityURN.NOTIFICATION));
-
- netconfSpy.onRemoteSessionUp(sessionCaps, listener);
-
- final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
- verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
- any(RemoteDeviceServices.class));
-
- List<String> notificationModulesName = List.of(
- org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
- .YangModuleInfoImpl.getInstance().getName().toString(),
- org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
- .YangModuleInfoImpl.getInstance().getName().toString());
-
- final Set<AvailableCapability> resolvedCapabilities = argument.getValue().capabilities().resolvedCapabilities();
+ void testNetconfDeviceNotificationsModelNotPresentWithCapability() {
+ final var netconfSpy = spy(new NetconfDeviceBuilder()
+ .setDeviceSchemaProvider(mockDeviceNetconfSchemaProvider())
+ .setProcessingExecutor(MoreExecutors.directExecutor())
+ .setId(getId())
+ .setSalFacade(facade)
+ .setBaseSchemaProvider(BASE_SCHEMAS)
+ .build());
- assertEquals(2, resolvedCapabilities.size());
- assertTrue(resolvedCapabilities.stream().anyMatch(entry -> notificationModulesName
- .contains(entry.getCapability())));
- }
+ netconfSpy.onRemoteSessionUp(getSessionCaps(false, CapabilityURN.NOTIFICATION),
+ listener);
- @Test
- public void testNetconfDeviceNotificationsCapabilityIsNotPresent() throws Exception {
- final RemoteDeviceHandler facade = getFacade();
- final NetconfDeviceCommunicator listener = getListener();
- final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
-
- final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
- getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
- final NetconfDevice device = new NetconfDeviceBuilder()
- .setSchemaResourcesDTO(schemaResourcesDTO)
- .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
- .setId(getId())
- .setSalFacade(facade)
- .setBaseSchemas(BASE_SCHEMAS)
- .build();
- final NetconfDevice netconfSpy = spy(device);
-
- final NetconfSessionPreferences sessionCaps = getSessionCaps(false,
- List.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
-
- netconfSpy.onRemoteSessionUp(sessionCaps, listener);
-
- final ArgumentCaptor<NetconfDeviceSchema> argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
+ final var argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
any(RemoteDeviceServices.class));
- final NetconfDeviceCapabilities netconfDeviceCaps = argument.getValue().capabilities();
-
- List<String> notificationModulesName = List.of(
- org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
- .YangModuleInfoImpl.getInstance().getName().toString(),
- org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
- .YangModuleInfoImpl.getInstance().getName().toString());
- assertFalse(netconfDeviceCaps.resolvedCapabilities().stream()
- .anyMatch(entry -> notificationModulesName.contains(entry.getCapability())));
+ assertEquals(Set.of(
+ new AvailableCapabilityBuilder()
+ .setCapability("(urn:ietf:params:xml:ns:yang:ietf-yang-types?revision=2013-07-15)ietf-yang-types")
+ .build(),
+ new AvailableCapabilityBuilder()
+ .setCapability("(urn:ietf:params:xml:ns:netconf:notification:1.0?revision=2008-07-14)notifications")
+ .build()), argument.getValue().capabilities().resolvedCapabilities());
}
@Test
- public void testNetconfDeviceNotificationsModelIsPresent() throws Exception {
- final RemoteDeviceHandler facade = getFacade();
- final NetconfDeviceCommunicator listener = getListener();
- final EffectiveModelContextFactory schemaContextProviderFactory = getSchemaFactory();
-
- final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry,
- getSchemaRepository(), schemaContextProviderFactory, STATE_SCHEMAS_RESOLVER);
- final NetconfDevice device = new NetconfDeviceBuilder()
- .setSchemaResourcesDTO(schemaResourcesDTO)
- .setGlobalProcessingExecutor(MoreExecutors.directExecutor())
- .setId(getId())
- .setSalFacade(facade)
- .setBaseSchemas(BASE_SCHEMAS)
- .build();
- final NetconfDevice netconfSpy = spy(device);
-
- final NetconfSessionPreferences sessionCaps = getSessionCaps(false, List.of());
-
- final var moduleBasedCaps = new HashMap<QName, CapabilityOrigin>();
- moduleBasedCaps.put(org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
- .YangModuleInfoImpl.getInstance().getName(),
- CapabilityOrigin.DeviceAdvertised);
- moduleBasedCaps.put(org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
- .YangModuleInfoImpl.getInstance().getName(),
- CapabilityOrigin.DeviceAdvertised);
+ void testNetconfDeviceNotificationsModelIsPresent() {
+ final var netconfSpy = spy(new NetconfDeviceBuilder()
+ .setDeviceSchemaProvider(mockDeviceNetconfSchemaProvider())
+ .setProcessingExecutor(MoreExecutors.directExecutor())
+ .setId(getId())
+ .setSalFacade(facade)
+ .setBaseSchemaProvider(BASE_SCHEMAS)
+ .build());
-
- netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), listener);
+ netconfSpy.onRemoteSessionUp(getSessionCaps(false).replaceModuleCaps(Map.of(
+ org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
+ .YangModuleInfoImpl.getInstance().getName(), CapabilityOrigin.DeviceAdvertised,
+ org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
+ .YangModuleInfoImpl.getInstance().getName(), CapabilityOrigin.DeviceAdvertised
+ )), listener);
final var argument = ArgumentCaptor.forClass(NetconfDeviceSchema.class);
verify(facade, timeout(5000)).onDeviceConnected(argument.capture(), any(NetconfSessionPreferences.class),
any(RemoteDeviceServices.class));
- final Set<AvailableCapability> resolvedCapabilities = argument.getValue().capabilities().resolvedCapabilities();
-
- final var notificationModulesName = List.of(
- org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714
- .YangModuleInfoImpl.getInstance().getName().toString(),
- org.opendaylight.yang.svc.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
- .YangModuleInfoImpl.getInstance().getName().toString());
- assertEquals(2, resolvedCapabilities.size());
- assertTrue(resolvedCapabilities.stream().anyMatch(entry -> notificationModulesName
- .contains(entry.getCapability())));
+ assertEquals(Set.of(
+ new AvailableCapabilityBuilder()
+ .setCapability("(urn:ietf:params:xml:ns:yang:ietf-yang-types?revision=2013-07-15)ietf-yang-types")
+ .setCapabilityOrigin(CapabilityOrigin.DeviceAdvertised)
+ .build(),
+ new AvailableCapabilityBuilder()
+ .setCapability("(urn:ietf:params:xml:ns:netconf:notification:1.0?revision=2008-07-14)notifications")
+ .setCapabilityOrigin(CapabilityOrigin.DeviceAdvertised)
+ .build()), argument.getValue().capabilities().resolvedCapabilities());
}
- private static EffectiveModelContextFactory getSchemaFactory() throws Exception {
- final EffectiveModelContextFactory schemaFactory = mock(EffectiveModelContextFactory.class);
+ private EffectiveModelContextFactory getSchemaFactory() {
doReturn(Futures.immediateFuture(SCHEMA_CONTEXT))
.when(schemaFactory).createEffectiveModelContext(anyCollection());
return schemaFactory;
}
- private static RemoteDeviceHandler getFacade() throws Exception {
- final RemoteDeviceHandler remoteDeviceHandler = mockCloseableClass(RemoteDeviceHandler.class);
- doNothing().when(remoteDeviceHandler).onDeviceConnected(
- any(NetconfDeviceSchema.class), any(NetconfSessionPreferences.class), any(RemoteDeviceServices.class));
- doNothing().when(remoteDeviceHandler).onDeviceDisconnected();
- doNothing().when(remoteDeviceHandler).onNotification(any(DOMNotification.class));
- return remoteDeviceHandler;
+ private DeviceNetconfSchemaProvider mockDeviceNetconfSchemaProvider() {
+ return mockDeviceNetconfSchemaProvider(getSchemaRepository(), getSchemaFactory());
}
- private static <T extends AutoCloseable> T mockCloseableClass(final Class<T> remoteDeviceHandlerClass)
- throws Exception {
- final T mock = mock(remoteDeviceHandlerClass);
- doNothing().when(mock).close();
- return mock;
+ private DeviceNetconfSchemaProvider mockDeviceNetconfSchemaProvider(final SchemaRepository schemaRepository,
+ final EffectiveModelContextFactory modelContextFactory) {
+ return new DefaultDeviceNetconfSchemaProvider(schemaRegistry, schemaRepository, modelContextFactory);
}
- public RemoteDeviceId getId() {
+ private static RemoteDeviceId getId() {
return new RemoteDeviceId("test-D", InetSocketAddress.createUnresolved("localhost", 22));
}
- public NetconfSessionPreferences getSessionCaps(final boolean addMonitor,
- final Collection<String> additionalCapabilities) {
+ private static NetconfSessionPreferences getSessionCaps(final boolean addMonitor,
+ final String... additionalCapabilities) {
final var capabilities = new ArrayList<String>();
capabilities.add(CapabilityURN.BASE);
capabilities.add(CapabilityURN.BASE_1_1);
if (addMonitor) {
capabilities.add(NetconfState.QNAME.getNamespace().toString());
}
- capabilities.addAll(additionalCapabilities);
+ capabilities.addAll(List.of(additionalCapabilities));
return NetconfSessionPreferences.fromStrings(capabilities);
}
-
- public NetconfDeviceCommunicator getListener() throws Exception {
- return mockCloseableClass(NetconfDeviceCommunicator.class);
- }
}