--- /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.verify;
+import static org.mockito.Mockito.when;
+import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_QNAME;
+import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toPath;
+
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Futures;
+import java.net.InetSocketAddress;
+import java.util.Arrays;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
+import org.opendaylight.netconf.sal.connect.netconf.sal.tx.AbstractWriteTx;
+import org.opendaylight.netconf.sal.connect.netconf.sal.tx.WriteCandidateRunningTx;
+import org.opendaylight.netconf.sal.connect.netconf.sal.tx.WriteCandidateTx;
+import org.opendaylight.netconf.sal.connect.netconf.sal.tx.WriteRunningTx;
+import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.$YangModuleInfoImpl;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public class NetconfDeviceDataBrokerTest {
+
+ @Mock
+ private DOMRpcService rpcService;
+ private SchemaContext schemaContext;
+ private NetconfDeviceDataBroker dataBroker;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ final ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create();
+ moduleInfoBackedContext.addModuleInfos(
+ Lists.newArrayList(
+ $YangModuleInfoImpl.getInstance(),
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.$YangModuleInfoImpl.getInstance()));
+ schemaContext = moduleInfoBackedContext.tryToCreateSchemaContext().get();
+ final DOMRpcResult result = new DefaultDOMRpcResult();
+ when(rpcService.invokeRpc(any(SchemaPath.class), any(NormalizedNode.class))).thenReturn(Futures.<DOMRpcResult, DOMRpcException>immediateCheckedFuture(result));
+
+ dataBroker = getDataBroker(NetconfMessageTransformUtil.NETCONF_CANDIDATE_URI.toString());
+ }
+
+ @Test
+ public void testNewReadOnlyTransaction() throws Exception {
+ final DOMDataReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction();
+ tx.read(LogicalDatastoreType.OPERATIONAL, null);
+ verify(rpcService).invokeRpc(eq(toPath(NETCONF_GET_QNAME)), any(ContainerNode.class));
+ }
+
+ @Test
+ public void testNewReadWriteTransaction() throws Exception {
+ final DOMDataReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
+ tx.read(LogicalDatastoreType.OPERATIONAL, null);
+ verify(rpcService).invokeRpc(eq(toPath(NETCONF_GET_QNAME)), any(ContainerNode.class));
+ }
+
+ @Test
+ public void testWritableRunningCandidateWriteTransaction() throws Exception {
+ testWriteTransaction(WriteCandidateRunningTx.class, NetconfMessageTransformUtil.NETCONF_RUNNING_WRITABLE_URI.toString(),
+ NetconfMessageTransformUtil.NETCONF_CANDIDATE_URI.toString());
+ }
+
+ @Test
+ public void testCandidateWriteTransaction() throws Exception {
+ testWriteTransaction(WriteCandidateTx.class, NetconfMessageTransformUtil.NETCONF_CANDIDATE_URI.toString());
+ }
+
+ @Test
+ public void testRunningWriteTransaction() throws Exception {
+ testWriteTransaction(WriteRunningTx.class, NetconfMessageTransformUtil.NETCONF_RUNNING_WRITABLE_URI.toString());
+ }
+
+ private void testWriteTransaction(final Class<? extends AbstractWriteTx> transaction, final String... capabilities) {
+ final NetconfDeviceDataBroker db = getDataBroker(capabilities);
+ Assert.assertEquals(transaction, db.newWriteOnlyTransaction().getClass());
+ }
+
+ private NetconfDeviceDataBroker getDataBroker(final String... caps) {
+ final NetconfSessionPreferences prefs = NetconfSessionPreferences.fromStrings(Arrays.asList(caps));
+ final RemoteDeviceId id = new RemoteDeviceId("device-1", InetSocketAddress.createUnresolved("localhost", 17830));
+ return new NetconfDeviceDataBroker(id, schemaContext, rpcService, prefs);
+ }
+
+}
\ 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.sal;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import java.net.URI;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListener;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public class NetconfDeviceNotificationServiceTest {
+
+ @Mock
+ private DOMNotificationListener listener1;
+ @Mock
+ private DOMNotificationListener listener2;
+ @Mock
+ private DOMNotification notification1;
+ @Mock
+ private DOMNotification notification2;
+
+ private NetconfDeviceNotificationService service;
+
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ SchemaPath path1 = SchemaPath.create(true, new QName(new URI("namespace1"), "path1"));
+ SchemaPath path2 = SchemaPath.create(true, new QName(new URI("namespace2"), "path2"));
+ service = new NetconfDeviceNotificationService();
+ service.registerNotificationListener(listener1, path1);
+ service.registerNotificationListener(listener2, path2);
+
+ doReturn(path1).when(notification1).getType();
+ doReturn(path2).when(notification2).getType();
+
+ }
+
+ @Test
+ public void testPublishNotification() throws Exception {
+
+ service.publishNotification(notification1);
+ verify(listener1).onNotification(notification1);
+ verify(listener2, never()).onNotification(notification1);
+
+ service.publishNotification(notification2);
+ verify(listener2).onNotification(notification2);
+ verify(listener1, never()).onNotification(notification2);
+ }
+
+}
\ 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.sal;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.util.xml.XmlUtil;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcAvailabilityListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcIdentifier;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
+import org.opendaylight.netconf.api.NetconfMessage;
+import org.opendaylight.netconf.sal.connect.api.RemoteDeviceCommunicator;
+import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.$YangModuleInfoImpl;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public class NetconfDeviceRpcTest {
+
+ @Mock
+ private DOMRpcAvailabilityListener listener;
+ @Mock
+ private RemoteDeviceCommunicator<NetconfMessage> communicator;
+
+ private NetconfDeviceRpc rpc;
+ private SchemaPath path;
+ private DOMRpcResult expectedReply;
+ private SchemaContext schema;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ schema = getSchema();
+ NetconfMessageTransformer transformer = new NetconfMessageTransformer(schema, true);
+ final NetconfMessage reply = new NetconfMessage(XmlUtil.readXmlToDocument(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"101\">\n" +
+ "<data>\n" +
+ "</data>\n" +
+ "</rpc-reply>"));
+ RpcResult<NetconfMessage> result = RpcResultBuilder.success(reply).build();
+ doReturn(Futures.immediateFuture(result)).when(communicator).sendRequest(any(NetconfMessage.class), any(QName.class));
+ rpc = new NetconfDeviceRpc(schema, communicator, transformer);
+
+ path = SchemaPath.create(true, QName.create("urn:ietf:params:xml:ns:netconf:base:1.0", "2011-06-01", "get-config"));
+ expectedReply = transformer.toRpcResult(reply, path);
+ }
+
+ @Test
+ public void testInvokeRpc() throws Exception {
+ NormalizedNode<?, ?> input = createNode("urn:ietf:params:xml:ns:netconf:base:1.0", "2011-06-01", "filter");
+ final CheckedFuture<DOMRpcResult, DOMRpcException> future = rpc.invokeRpc(path, input);
+ final DOMRpcResult result = future.checkedGet();
+ Assert.assertEquals(expectedReply, result);
+ }
+
+ @Test
+ public void testRegisterRpcListener() throws Exception {
+ ArgumentCaptor<Collection> argument = ArgumentCaptor.forClass(Collection.class);
+
+ rpc.registerRpcListener(listener);
+
+ verify(listener).onRpcAvailable(argument.capture());
+ final Collection<DOMRpcIdentifier> argValue = argument.getValue();
+ final Set<RpcDefinition> operations = schema.getOperations();
+ Assert.assertEquals(argValue.size(), operations.size());
+ for (RpcDefinition operation : operations) {
+ final DOMRpcIdentifier domRpcIdentifier = DOMRpcIdentifier.create(operation.getPath());
+ Assert.assertTrue(argValue.contains(domRpcIdentifier));
+
+ }
+ }
+
+ private static ContainerNode createNode(String namespace, String date, String localName) {
+ return Builders.containerBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create(namespace, date, localName))).build();
+ }
+
+ private static SchemaContext getSchema() {
+ final ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create();
+ moduleInfoBackedContext.addModuleInfos(Collections.singleton($YangModuleInfoImpl.getInstance()));
+ return moduleInfoBackedContext.tryToCreateSchemaContext().get();
+ }
+}
\ 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.schema;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.sun.org.apache.xerces.internal.dom.DocumentImpl;
+import java.net.InetSocketAddress;
+import java.util.Collections;
+import javax.xml.transform.dom.DOMSource;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
+import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAnyXmlNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+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.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class NetconfRemoteSchemaYangSourceProviderTest {
+
+ @Mock
+ private DOMRpcService service;
+
+ private NetconfRemoteSchemaYangSourceProvider provider;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ final DOMRpcResult value = new DefaultDOMRpcResult(getNode(), Collections.<RpcError>emptySet());
+ CheckedFuture<DOMRpcResult, DOMRpcException> response = Futures.immediateCheckedFuture(value);
+ doReturn(response).when(service).invokeRpc(any(SchemaPath.class), any(NormalizedNode.class));
+
+ provider = new NetconfRemoteSchemaYangSourceProvider(new RemoteDeviceId("device1", InetSocketAddress.createUnresolved("localhost", 17830)), service);
+ }
+
+ @Test
+ public void testGetSource() throws Exception {
+ final SourceIdentifier identifier = SourceIdentifier.create("test", Optional.of("2016-02-08"));
+ final CheckedFuture<YangTextSchemaSource, SchemaSourceException> module = provider.getSource(identifier);
+ final YangTextSchemaSource source = module.checkedGet();
+ Assert.assertEquals(identifier, source.getIdentifier());
+ verify(service).invokeRpc(
+ SchemaPath.create(true, NetconfMessageTransformUtil.GET_SCHEMA_QNAME),
+ NetconfRemoteSchemaYangSourceProvider.createGetSchemaRequest(identifier.getName(), Optional.of(identifier.getRevision()))
+ );
+ }
+
+ private static NormalizedNode getNode() {
+ final YangInstanceIdentifier.NodeIdentifier id = YangInstanceIdentifier.NodeIdentifier.create(
+ QName.create("urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring", "2010-10-04", "output")
+ );
+ final YangInstanceIdentifier.NodeIdentifier childId = YangInstanceIdentifier.NodeIdentifier.create(
+ QName.create("urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring", "2010-10-04", "data")
+ );
+ Document xmlDoc = new DocumentImpl();
+ Element root = xmlDoc.createElement("data");
+ root.setTextContent("module test {}");
+ final DOMSource v = new DOMSource(root);
+ DataContainerChild<?, ?> child = ImmutableAnyXmlNodeBuilder.create().withNodeIdentifier(childId).withValue(v).build();
+ return ImmutableContainerNodeBuilder.create().withNodeIdentifier(id).withChild(child).build();
+ }
+
+}
\ No newline at end of file