--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netconf.confignetconfconnector.osgi;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.controller.config.facade.xml.ConfigSubsystemFacade;
+import org.opendaylight.netconf.confignetconfconnector.operations.Commit;
+import org.opendaylight.netconf.confignetconfconnector.operations.DiscardChanges;
+import org.opendaylight.netconf.confignetconfconnector.operations.Lock;
+import org.opendaylight.netconf.confignetconfconnector.operations.UnLock;
+import org.opendaylight.netconf.confignetconfconnector.operations.Validate;
+import org.opendaylight.netconf.confignetconfconnector.operations.editconfig.EditConfig;
+import org.opendaylight.netconf.confignetconfconnector.operations.get.Get;
+import org.opendaylight.netconf.confignetconfconnector.operations.getconfig.GetConfig;
+import org.opendaylight.netconf.confignetconfconnector.operations.runtimerpc.RuntimeRpc;
+import org.opendaylight.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.netconf.mapping.api.NetconfOperationService;
+
+public class NetconfOperationServiceImplTest {
+
+ @Test
+ public void testOperationService() {
+ final ConfigSubsystemFacade configSubsystemFacade = mock(ConfigSubsystemFacade.class);
+ final NetconfOperationService netconfOperationService =
+ new NetconfOperationServiceImpl(configSubsystemFacade, "reportingID");
+
+ // testing operations in Set from NetconfOperationProvider
+
+ Set<NetconfOperation> operations = netconfOperationService.getNetconfOperations();
+
+ assertTrue(containInstance(operations, GetConfig.class));
+ assertTrue(containInstance(operations, EditConfig.class));
+ assertTrue(containInstance(operations, Commit.class));
+ assertTrue(containInstance(operations, Lock.class));
+ assertTrue(containInstance(operations, UnLock.class));
+ assertTrue(containInstance(operations, Get.class));
+ assertTrue(containInstance(operations, DiscardChanges.class));
+ assertTrue(containInstance(operations, Validate.class));
+ assertTrue(containInstance(operations, RuntimeRpc.class));
+
+ // verify closing service
+
+ doNothing().when(configSubsystemFacade).close();
+ netconfOperationService.close();
+
+ verify(configSubsystemFacade, times(1)).close();
+ }
+
+ private boolean containInstance(final Set<NetconfOperation> operations, final Class<?> cls) {
+ return operations.stream().filter(cls::isInstance).findFirst().isPresent();
+ }
+}
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.ModifyAction;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
final XmlElement configElement = getElement(operationElement, CONFIG_KEY);
- for (XmlElement element : configElement.getChildElements()) {
+ for (final XmlElement element : configElement.getChildElements()) {
final String ns = element.getNamespace();
final DataSchemaNode schemaNode = getSchemaNodeFromNamespace(ns, element).get();
}
private void executeChange(final DOMDataReadWriteTransaction rwtx, final DataTreeChange change) throws DocumentedException {
+ final YangInstanceIdentifier path = YangInstanceIdentifier.create(change.getPath());
+ final NormalizedNode<?, ?> changeData = change.getChangeRoot();
switch (change.getAction()) {
case NONE:
return;
case MERGE:
- rwtx.merge(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(change.getPath()), change.getChangeRoot());
+ createMapNodeIfNonExistent(rwtx, path, changeData);
+ rwtx.merge(LogicalDatastoreType.CONFIGURATION, path, changeData);
break;
case CREATE:
try {
- final Optional<NormalizedNode<?, ?>> readResult = rwtx.read(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(change.getPath())).checkedGet();
+ final Optional<NormalizedNode<?, ?>> readResult = rwtx.read(LogicalDatastoreType.CONFIGURATION, path).checkedGet();
if (readResult.isPresent()) {
throw new DocumentedException("Data already exists, cannot execute CREATE operation", ErrorType.protocol, ErrorTag.data_exists, ErrorSeverity.error);
}
- rwtx.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(change.getPath()), change.getChangeRoot());
- } catch (ReadFailedException e) {
+ createMapNodeIfNonExistent(rwtx, path, changeData);
+ rwtx.put(LogicalDatastoreType.CONFIGURATION, path, changeData);
+ } catch (final ReadFailedException e) {
LOG.warn("Read from datastore failed when trying to read data for create operation", change, e);
}
break;
case REPLACE:
- rwtx.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(change.getPath()), change.getChangeRoot());
+ createMapNodeIfNonExistent(rwtx, path, changeData);
+ rwtx.put(LogicalDatastoreType.CONFIGURATION, path, changeData);
break;
case DELETE:
try {
- final Optional<NormalizedNode<?, ?>> readResult = rwtx.read(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(change.getPath())).checkedGet();
+ final Optional<NormalizedNode<?, ?>> readResult = rwtx.read(LogicalDatastoreType.CONFIGURATION, path).checkedGet();
if (!readResult.isPresent()) {
throw new DocumentedException("Data is missing, cannot execute DELETE operation", ErrorType.protocol, ErrorTag.data_missing, ErrorSeverity.error);
}
- rwtx.delete(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(change.getPath()));
- } catch (ReadFailedException e) {
+ rwtx.delete(LogicalDatastoreType.CONFIGURATION, path);
+ } catch (final ReadFailedException e) {
LOG.warn("Read from datastore failed when trying to read data for delete operation", change, e);
}
break;
case REMOVE:
- rwtx.delete(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(change.getPath()));
+ rwtx.delete(LogicalDatastoreType.CONFIGURATION, path);
break;
default:
LOG.warn("Unknown/not implemented operation, not executing");
}
}
+ private void createMapNodeIfNonExistent(final DOMDataReadWriteTransaction rwtx, final YangInstanceIdentifier path,
+ final NormalizedNode change) throws DocumentedException {
+ if (!(change instanceof MapEntryNode)) {
+ return;
+ }
+ final YangInstanceIdentifier mapNodeYid = path.getParent();
+ try {
+ final Boolean mapNodeExists = rwtx.exists(LogicalDatastoreType.CONFIGURATION, mapNodeYid).checkedGet();
+ if (!mapNodeExists) {
+ final MapNode mixinNode = Builders.mapBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(mapNodeYid.getLastPathArgument().getNodeType()))
+ .build();
+ rwtx.put(LogicalDatastoreType.CONFIGURATION, mapNodeYid, mixinNode);
+ }
+ } catch (final ReadFailedException e) {
+ throw new DocumentedException("List node existence check failed", e, ErrorType.protocol, ErrorTag.data_missing, ErrorSeverity.error);
+
+ }
+ }
+
private NormalizedNode parseIntoNormalizedNode(final DataSchemaNode schemaNode, final XmlElement element,
final DomToNormalizedNodeParserFactory.BuildingStrategyProvider editOperationStrategyProvider) {
throw new NetconfDocumentedException("Unable to find module by namespace: " + namespace,
ErrorType.application, ErrorTag.unknown_namespace, ErrorSeverity.error);
}
- DataSchemaNode schemaNode =
+ final DataSchemaNode schemaNode =
module.getDataChildByName(QName.create(module.getQNameModule(), element.getName()));
if (schemaNode != null) {
dataSchemaNode = Optional.of(schemaNode);
ErrorTag.unknown_namespace,
ErrorSeverity.error);
}
- } catch (URISyntaxException e) {
+ } catch (final URISyntaxException e) {
LOG.debug("Unable to create URI for namespace : {}", namespace);
}
}
- private XmlElement getElement(final XmlElement operationElement, String elementName) throws DocumentedException {
+ private XmlElement getElement(final XmlElement operationElement, final String elementName) throws DocumentedException {
final Optional<XmlElement> childNode = operationElement.getOnlyChildElementOptionally(elementName);
if (!childNode.isPresent()) {
throw new DocumentedException(elementName + " element is missing",
deleteDatastore();
}
+ @Test
+ public void testReplaceMapEntry() throws Exception {
+ verifyResponse(edit("messages/mapping/editConfigs/edit-config-replace-map-entry.xml"), RPC_REPLY_OK);
+ verifyResponse(commit(), RPC_REPLY_OK);
+ verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/get-config-map-entry.xml"));
+ }
+
+ @Test
+ public void testMergeMapEntry() throws Exception {
+ verifyResponse(edit("messages/mapping/editConfigs/edit-config-merge-map-entry.xml"), RPC_REPLY_OK);
+ verifyResponse(commit(), RPC_REPLY_OK);
+ verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/get-config-map-entry.xml"));
+ }
+
@Test
public void testFiltering() throws Exception {
--- /dev/null
+<!--
+ ~ Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ ~
+ ~ This program and the accompanying materials are made available under the
+ ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+ -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <edit-config>
+ <target>
+ <candidate/>
+ </target>
+ <default-operation>none</default-operation>
+ <config>
+ <mapping-nodes xmlns="urn:opendaylight:mdsal:mapping:test">
+ <mapping-node xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="merge">
+ <id>id1</id>
+ <content>content1</content>
+ </mapping-node>
+ </mapping-nodes>
+ </config>
+ </edit-config>
+</rpc>
\ No newline at end of file
--- /dev/null
+<!--
+ ~ Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ ~
+ ~ This program and the accompanying materials are made available under the
+ ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+ -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <edit-config>
+ <target>
+ <candidate/>
+ </target>
+ <default-operation>none</default-operation>
+ <config>
+ <mapping-nodes xmlns="urn:opendaylight:mdsal:mapping:test">
+ <mapping-node xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="replace">
+ <id>id1</id>
+ <content>content1</content>
+ </mapping-node>
+ </mapping-nodes>
+ </config>
+ </edit-config>
+</rpc>
\ No newline at end of file
--- /dev/null
+<!--
+ ~ Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ ~
+ ~ This program and the accompanying materials are made available under the
+ ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+ -->
+
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" a="64" id="a" message-id="101" xmlnx="a:b:c:d">
+ <data>
+ <mapping-nodes xmlns="urn:opendaylight:mdsal:mapping:test">
+ <mapping-node>
+ <id>id1</id>
+ <content>content1</content>
+ </mapping-node>
+ </mapping-nodes>
+ </data>
+</rpc-reply>
\ No newline at end of file
package org.opendaylight.netconf.notifications.impl.osgi;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.Dictionary;
operationaServiceRegistration = null;
}
}
+
+ @VisibleForTesting
+ NetconfNotificationManager getNetconfNotificationManager() {
+ return netconfNotificationManager;
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netconf.notifications.impl.osgi;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+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 java.util.Collections;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Set;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.opendaylight.controller.config.util.capability.BasicCapability;
+import org.opendaylight.controller.config.util.capability.Capability;
+import org.opendaylight.netconf.api.monitoring.CapabilityListener;
+import org.opendaylight.netconf.api.util.NetconfConstants;
+import org.opendaylight.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.netconf.notifications.NetconfNotification;
+import org.opendaylight.netconf.notifications.NetconfNotificationCollector;
+import org.opendaylight.netconf.notifications.impl.NetconfNotificationManager;
+import org.opendaylight.netconf.notifications.impl.ops.CreateSubscription;
+import org.opendaylight.netconf.notifications.impl.ops.Get;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+public class ActivatorTest {
+
+ @Test
+ public void testActivator() throws Exception {
+ final Activator activator = new Activator();
+ final BundleContext context = mock(BundleContext.class);
+
+
+ final ServiceRegistration netconfNotificationCollectorServiceRegistration = mock(ServiceRegistration.class);
+ final ServiceRegistration operationaServiceRegistration = mock(ServiceRegistration.class);
+
+ // test registering services
+ doReturn(netconfNotificationCollectorServiceRegistration).when(context).
+ registerService(eq(NetconfNotificationCollector.class), any(NetconfNotificationManager.class), any());
+ doReturn(operationaServiceRegistration).when(context).
+ registerService(eq(NetconfOperationServiceFactory.class), any(NetconfOperationServiceFactory.class), any());
+
+ activator.start(context);
+
+ verify(context, times(1)).registerService(eq(NetconfNotificationCollector.class),
+ any(NetconfNotificationManager.class), eq(new Hashtable<>()));
+
+ final ArgumentCaptor<NetconfOperationServiceFactory> serviceFactoryArgumentCaptor =
+ ArgumentCaptor.forClass(NetconfOperationServiceFactory.class);
+
+ final Dictionary<String, String> properties = new Hashtable<>();
+ properties.put(NetconfConstants.SERVICE_NAME, NetconfConstants.NETCONF_MONITORING);
+
+ verify(context, times(1)).registerService(eq(NetconfOperationServiceFactory.class),
+ serviceFactoryArgumentCaptor.capture(), eq(properties));
+
+ // test service factory argument requisites
+ final NetconfOperationServiceFactory serviceFactory = serviceFactoryArgumentCaptor.getValue();
+
+ final Set<Capability> capabilities = Collections.singleton(new BasicCapability(NetconfNotification.NOTIFICATION_NAMESPACE));
+
+ assertEquals(capabilities.iterator().next().getCapabilityUri(), serviceFactory.getCapabilities().iterator().next().getCapabilityUri());
+ assertEquals(capabilities.iterator().next().getCapabilitySchema(), serviceFactory.getCapabilities().iterator().next().getCapabilitySchema());
+ assertEquals(capabilities.iterator().next().getModuleNamespace(), serviceFactory.getCapabilities().iterator().next().getModuleNamespace());
+ assertEquals(capabilities.iterator().next().getModuleName(), serviceFactory.getCapabilities().iterator().next().getModuleName());
+
+ final CapabilityListener listener = mock(CapabilityListener.class);
+
+ doNothing().when(listener).onCapabilitiesChanged(any(), any());
+
+ serviceFactory.registerCapabilityListener(listener);
+
+ verify(listener).onCapabilitiesChanged(serviceFactory.getCapabilities(), Collections.emptySet());
+
+ final NetconfOperationService netconfOperationService = serviceFactory.createService("id");
+ final Set<NetconfOperation> netconfOperations = netconfOperationService.getNetconfOperations();
+
+ final CreateSubscription createSubscription = new CreateSubscription("id", activator.getNetconfNotificationManager());
+
+ netconfOperations.forEach(
+ operation -> {
+ if (operation instanceof CreateSubscription) {
+ assertEquals(createSubscription.toString(), operation.toString());
+ }
+ if (operation instanceof Get) {
+ assertEquals("id", ((Get) operation).getNetconfSessionIdForReporting());
+ }
+ }
+ );
+
+ // test unregister after stop
+ doNothing().when(netconfNotificationCollectorServiceRegistration).unregister();
+ doNothing().when(operationaServiceRegistration).unregister();
+
+ activator.stop(context);
+
+ verify(netconfNotificationCollectorServiceRegistration, times(1)).unregister();
+ verify(operationaServiceRegistration, times(1)).unregister();
+
+ }
+
+
+}
<artifactId>sal-distributed-datastore</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<scm>
*/
package org.opendaylight.netconf.sal.connect.netconf;
+import com.google.common.annotations.VisibleForTesting;
import org.opendaylight.netconf.api.NetconfMessage;
import org.opendaylight.netconf.sal.connect.api.RemoteDevice;
import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
messageTransformer = new SchemalessMessageTransformer(counter);
}
+ @VisibleForTesting
+ SchemalessNetconfDevice(final RemoteDeviceId id, final RemoteDeviceHandler<NetconfSessionPreferences> salFacade,
+ final SchemalessMessageTransformer messageTransformer) {
+ this.id = id;
+ this.salFacade = salFacade;
+ final MessageCounter counter = new MessageCounter();
+ rpcTransformer = new BaseRpcSchemalessTransformer(counter);
+ this.messageTransformer = messageTransformer;
+ }
+
@Override public void onRemoteSessionUp(final NetconfSessionPreferences remoteSessionCapabilities,
final NetconfDeviceCommunicator netconfDeviceCommunicator) {
final SchemalessNetconfDeviceRpc schemalessNetconfDeviceRpc = new SchemalessNetconfDeviceRpc(id,
*/
package org.opendaylight.netconf.sal.connect.netconf.sal;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import java.util.List;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
registerToSal(domBroker, bindingBroker);
}
+ @VisibleForTesting
+ NetconfDeviceSalFacade(final RemoteDeviceId id, NetconfDeviceSalProvider salProvider,
+ final Broker domBroker, final BindingAwareBroker bindingBroker) {
+ this.id = id;
+ this.salProvider = salProvider;
+ registerToSal(domBroker, bindingBroker);
+ }
+
public void registerToSal(final Broker domRegistryDependency, final BindingAwareBroker bindingBroker) {
domRegistryDependency.registerProvider(salProvider);
bindingBroker.registerProvider(salProvider);
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netconf.sal.connect.netconf;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.collect.Lists;
+import java.lang.reflect.Field;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Collection;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.netconf.api.NetconfMessage;
+import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
+import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceRpc;
+import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.SchemalessMessageTransformer;
+import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class SchemalessNetconfDeviceTest {
+
+ 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";
+
+ @Test
+ public void testSessionOnMethods() throws Exception {
+ final RemoteDeviceHandler<NetconfSessionPreferences> facade = getFacade();
+ final NetconfDeviceCommunicator listener = mockCloseableClass(NetconfDeviceCommunicator.class);
+ final SchemalessMessageTransformer messageTransformer = mock(SchemalessMessageTransformer.class);
+ final RemoteDeviceId remoteDeviceId = new RemoteDeviceId("test-D",
+ InetSocketAddress.createUnresolved("localhost", 22));
+ final Throwable throwable = new Throwable();
+
+ final SchemalessNetconfDevice device = new SchemalessNetconfDevice(remoteDeviceId, facade, messageTransformer);
+
+ final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
+ Lists.newArrayList(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
+
+ final NetconfMessage netconfMessage = mock(NetconfMessage.class);
+
+ device.onRemoteSessionUp(sessionCaps, listener);
+ verify(facade).onDeviceConnected(any(SchemaContext.class), any(NetconfSessionPreferences.class), any(DOMRpcService.class));
+
+ device.onNotification(netconfMessage);
+ verify(facade).onNotification(any(DOMNotification.class));
+
+ device.onRemoteSessionDown();
+ verify(facade).onDeviceDisconnected();
+
+ device.onRemoteSessionFailed(throwable);
+ verify(facade).onDeviceFailed(throwable);
+ }
+
+ @SuppressWarnings("unchecked")
+ private RemoteDeviceHandler<NetconfSessionPreferences> getFacade() throws Exception {
+ final RemoteDeviceHandler<NetconfSessionPreferences> remoteDeviceHandler = mockCloseableClass(RemoteDeviceHandler.class);
+ doNothing().when(remoteDeviceHandler).onDeviceConnected(any(SchemaContext.class), any(NetconfSessionPreferences.class), any(NetconfDeviceRpc.class));
+ doNothing().when(remoteDeviceHandler).onDeviceDisconnected();
+ doNothing().when(remoteDeviceHandler).onNotification(any(DOMNotification.class));
+ return remoteDeviceHandler;
+ }
+
+ private <T extends AutoCloseable> T mockCloseableClass(final Class<T> remoteDeviceHandlerClass) throws Exception {
+ final T mock = mockClass(remoteDeviceHandlerClass);
+ doNothing().when(mock).close();
+ return mock;
+ }
+
+ private static <T> T mockClass(final Class<T> remoteDeviceHandlerClass) {
+ final T mock = mock(remoteDeviceHandlerClass);
+ Mockito.doReturn(remoteDeviceHandlerClass.getSimpleName()).when(mock).toString();
+ return mock;
+ }
+
+ private NetconfSessionPreferences getSessionCaps(final boolean addMonitor, final Collection<String> additionalCapabilities) {
+ final ArrayList<String> capabilities = Lists.newArrayList(
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_0,
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_1);
+
+ if(addMonitor) {
+ capabilities.add(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING.getNamespace().toString());
+ }
+
+ capabilities.addAll(additionalCapabilities);
+
+ return NetconfSessionPreferences.fromStrings(
+ capabilities);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netconf.sal.connect.netconf.sal;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+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 static org.mockito.MockitoAnnotations.initMocks;
+
+import java.net.InetSocketAddress;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
+import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({NetconfDeviceTopologyAdapter.class, NetconfDeviceSalProvider.MountInstance.class, NetconfSessionPreferences.class})
+public class NetconfDeviceSalFacadeTest {
+
+ private NetconfDeviceSalFacade deviceFacade;
+
+ private NetconfDeviceTopologyAdapter netconfDeviceTopologyAdapter;
+ private NetconfDeviceSalProvider.MountInstance mountInstance;
+
+ @Mock
+ private NetconfDeviceSalProvider salProvider;
+
+ @Before
+ public void setUp() throws Exception{
+ initMocks(this);
+ final InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8000);
+ final RemoteDeviceId remoteDeviceId = new RemoteDeviceId("test", address);
+
+ final Broker domRegistry = mock(Broker.class);
+ final BindingAwareBroker bindingRegistry = mock(BindingAwareBroker.class);
+ deviceFacade = new NetconfDeviceSalFacade(remoteDeviceId, salProvider, domRegistry, bindingRegistry);
+
+ netconfDeviceTopologyAdapter = PowerMockito.mock(NetconfDeviceTopologyAdapter.class);
+ mountInstance = PowerMockito.mock(NetconfDeviceSalProvider.MountInstance.class);
+
+ doReturn(netconfDeviceTopologyAdapter).when(salProvider).getTopologyDatastoreAdapter();
+ doNothing().when(netconfDeviceTopologyAdapter).updateDeviceData(any(Boolean.class), any(NetconfDeviceCapabilities.class));
+
+ doReturn(mountInstance).when(salProvider).getMountInstance();
+ doNothing().when(mountInstance).onTopologyDeviceDisconnected();
+ }
+
+ @Test
+ public void testOnDeviceDisconnected() {
+ deviceFacade.onDeviceDisconnected();
+
+ verify(netconfDeviceTopologyAdapter).updateDeviceData(eq(false), any(NetconfDeviceCapabilities.class));
+ verify(mountInstance, times(1)).onTopologyDeviceDisconnected();
+
+ }
+
+ @Test
+ public void testOnDeviceFailed() {
+ final Throwable throwable = new Throwable();
+ deviceFacade.onDeviceFailed(throwable);
+
+ verify(netconfDeviceTopologyAdapter).setDeviceAsFailed(throwable);
+ verify(mountInstance, times(1)).onTopologyDeviceDisconnected();
+ }
+
+ @Test
+ public void testOnDeviceClose() throws Exception {
+ deviceFacade.close();
+ verify(salProvider).close();
+ }
+
+ @Test
+ public void testOnDeviceConnected() {
+ final SchemaContext schemaContext = mock(SchemaContext.class);
+
+ final NetconfSessionPreferences netconfSessionPreferences = NetconfSessionPreferences.fromStrings(getCapabilities());
+
+ final DOMRpcService deviceRpc = mock(DOMRpcService.class);
+ deviceFacade.onDeviceConnected(schemaContext, netconfSessionPreferences, deviceRpc);
+
+ verify(mountInstance, times(1)).onTopologyDeviceConnected(eq(schemaContext), any(DOMDataBroker.class), eq(deviceRpc), any(NetconfDeviceNotificationService.class));
+ verify(netconfDeviceTopologyAdapter, times(1)).updateDeviceData(true, netconfSessionPreferences.getNetconfDeviceCapabilities());
+ }
+
+ @Test
+ public void testOnDeviceNotification() throws Exception {
+ final DOMNotification domNotification = mock(DOMNotification.class);
+ deviceFacade.onNotification(domNotification);
+ verify(mountInstance).publish(domNotification);
+ }
+
+ private List<String> getCapabilities(){
+ return Arrays.asList(NetconfMessageTransformUtil.NETCONF_CANDIDATE_URI.toString());
+ }
+}
import java.util.Arrays;
import java.util.EnumMap;
import java.util.List;
-import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import javassist.ClassPool;
-import org.custommonkey.xmlunit.XMLUnit;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.internal.util.collections.Sets;
import org.opendaylight.controller.cluster.databroker.ConcurrentDOMDataBroker;
-import org.opendaylight.controller.cluster.datastore.node.utils.AugmentationIdentifierGenerator;
-import org.opendaylight.controller.md.sal.binding.impl.BindingDOMDataBrokerAdapter;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.impl.BindingDOMDataBrokerAdapter;
import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory;
import org.opendaylight.controller.sal.core.spi.data.DOMStore;
import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeFields;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator;
import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
};
}
+ @Test
+ public void testRemoveDeviceConfiguration() throws Exception {
+ doReturn(Futures.immediateCheckedFuture(null)).when(writeTx).submit();
+
+ NetconfDeviceTopologyAdapter adapter = new NetconfDeviceTopologyAdapter(id, txChain);
+ adapter.close();
+
+ verify(txChain, times(2)).newWriteOnlyTransaction();
+ verify(writeTx).delete(LogicalDatastoreType.OPERATIONAL, id.getTopologyBindingPath());
+ verify(writeTx, times(2)).submit();
+ }
+
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netconf.sal.connect.netconf.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import java.net.InetSocketAddress;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+
+public class RemoteDeviceIdTest {
+
+ @Test
+ public void testEquals() {
+ final InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8000);
+ final ModuleIdentifier identifier = new ModuleIdentifier("test", "test");
+
+ final RemoteDeviceId remoteDeviceId = new RemoteDeviceId("test", address);
+ final RemoteDeviceId remoteDeviceIdEqualName = new RemoteDeviceId(identifier, address);
+ final RemoteDeviceId remoteDeviceIdDiffName = new RemoteDeviceId("test-diff", address);
+
+ assertEquals(true, remoteDeviceId.equals(remoteDeviceId));
+ assertEquals(false, remoteDeviceId.equals(this));
+ assertEquals(false, remoteDeviceId.equals(remoteDeviceIdDiffName));
+ assertEquals(true, remoteDeviceId.equals(remoteDeviceIdEqualName));
+ }
+
+ @Test
+ public void testHashCode() {
+ final String name = "name";
+ final InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8000);
+ final RemoteDeviceId remoteDeviceId = new RemoteDeviceId(name, address);
+ final RemoteDeviceId remoteDeviceIdEqualName = new RemoteDeviceId(name, address);
+ final RemoteDeviceId remoteDeviceIdDiffName = new RemoteDeviceId("test-diff", address);
+
+ assertEquals(remoteDeviceIdEqualName.hashCode(), remoteDeviceId.hashCode());
+ assertNotEquals(remoteDeviceIdDiffName.hashCode(), remoteDeviceId.hashCode());
+ }
+}
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
import java.io.IOException;
import org.opendaylight.yanglib.api.YangLibService;
import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
-import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class YangLibServiceImpl implements YangLibService {
private static final Logger LOG = LoggerFactory.getLogger(YangLibServiceImpl.class);
- private SharedSchemaRepository schemaRepository;
+ private SchemaRepository schemaRepository;
public YangLibServiceImpl() {
}
- public void setSchemaRepository(final SharedSchemaRepository schemaRepository) {
+ public void setSchemaRepository(final SchemaRepository schemaRepository) {
LOG.debug("Setting schema repository {}", schemaRepository);
this.schemaRepository = schemaRepository;
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.yanglib.impl;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.BDDMockito;
+import org.opendaylight.yanglib.api.YangLibRestAppService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(FrameworkUtil.class)
+public class YangLibRestAppTest {
+
+ @Test
+ public void testYangLibRestApp() {
+ PowerMockito.mockStatic(FrameworkUtil.class);
+
+ final BundleContext bundleContext = mock(BundleContext.class);
+ final Bundle bundle = mock(Bundle.class);
+
+ BDDMockito.given(FrameworkUtil.getBundle(any())).willReturn(bundle);
+ when(bundle.getBundleContext()).thenReturn(bundleContext);
+
+ final YangLibRestApp yangLibRestApp = new YangLibRestApp();
+ final Set singleton = yangLibRestApp.getSingletons();
+
+ assertTrue(singleton.contains(yangLibRestApp.getYangLibService()));
+
+ verify(bundleContext, times(1)).registerService(eq(YangLibRestAppService.class.getName()), eq(yangLibRestApp), eq(null));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.yanglib.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+
+public class YangLibServiceImplTest {
+
+ private final static String TEST_OUTPUT_STRING = "hello world";
+
+ @Test
+ public void testSchema() throws SchemaSourceException {
+
+ final SchemaRepository schemaRepository = mock(SchemaRepository.class);
+ final YangLibServiceImpl yangLibService = new YangLibServiceImpl();
+ yangLibService.setSchemaRepository(schemaRepository);
+
+ final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier.create("name", "2016-01-01");
+
+ final YangTextSchemaSource yangTextSchemaSource = new YangTextSchemaSource(sourceIdentifier) {
+ @Override
+ protected MoreObjects.ToStringHelper addToStringAttributes(MoreObjects.ToStringHelper toStringHelper) {
+ return null;
+ }
+
+ @Override
+ public InputStream openStream() throws IOException {
+ return new ByteArrayInputStream(TEST_OUTPUT_STRING.getBytes());
+ }
+ };
+
+ final CheckedFuture<YangTextSchemaSource, SchemaSourceException> sourceFuture =
+ Futures.immediateCheckedFuture(yangTextSchemaSource);
+ doReturn(sourceFuture).when(schemaRepository).getSchemaSource(any(SourceIdentifier.class),
+ eq(YangTextSchemaSource.class));
+
+ final String outputStream = yangLibService.getSchema("name", "2016-01-01");
+ assertEquals(TEST_OUTPUT_STRING, outputStream);
+ }
+
+}
</dependencies>
</dependencyManagement>
- <build>
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-checkstyle-plugin</artifactId>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>checkstyle</artifactId>
- <version>0.4.0-SNAPSHOT</version>
- </dependency>
- </dependencies>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
-
<profiles>
<profile>
<id>integrationtests</id>