Merge "Bug 6635: Correct WriteRunningTx behavior"
[netconf.git] / netconf / sal-netconf-connector / src / test / java / org / opendaylight / netconf / sal / connect / netconf / sal / tx / WriteRunningTxTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netconf.sal.connect.netconf.sal.tx;
10
11 import static org.mockito.Matchers.any;
12 import static org.mockito.Matchers.eq;
13 import static org.mockito.Mockito.doReturn;
14 import static org.mockito.Mockito.never;
15 import static org.mockito.Mockito.times;
16 import static org.mockito.Mockito.verify;
17
18 import com.google.common.collect.ImmutableList;
19 import com.google.common.util.concurrent.Futures;
20 import java.io.InputStream;
21 import java.net.InetSocketAddress;
22 import org.junit.Before;
23 import org.junit.Test;
24 import org.mockito.Mock;
25 import org.mockito.MockitoAnnotations;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
28 import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
29 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps;
30 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
31 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
32 import org.opendaylight.yangtools.yang.common.QName;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
34 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
36 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
37 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
38 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
39 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
40 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
41 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
42
43 public class WriteRunningTxTest {
44
45     @Mock
46     private DOMRpcService rpc;
47     private NetconfBaseOps netconfOps;
48     private RemoteDeviceId id;
49
50     @Before
51     public void setUp() throws Exception {
52         MockitoAnnotations.initMocks(this);
53         final SchemaContext schemaContext = parseYangStreams(getClass().getResourceAsStream("/schemas/test-module.yang"));
54         doReturn(Futures.immediateCheckedFuture(new DefaultDOMRpcResult())).when(rpc).invokeRpc(any(), any());
55         netconfOps = new NetconfBaseOps(rpc, schemaContext);
56         id = new RemoteDeviceId("device1", InetSocketAddress.createUnresolved("0.0.0.0", 17830));
57     }
58
59     @Test
60     public void testSubmit() throws Exception {
61         final WriteRunningTx tx = new WriteRunningTx(id, netconfOps, true);
62         //check, if lock is called
63         verify(rpc).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_LOCK_QNAME)), any());
64         final QName qName1 = QName.create("test:namespace", "2013-07-22", "c");
65         final YangInstanceIdentifier yid1 = YangInstanceIdentifier.builder()
66                 .node(qName1)
67                 .build();
68         final QName qName2 = QName.create(qName1, "a");
69         final YangInstanceIdentifier yid2 = YangInstanceIdentifier.builder()
70                 .node(qName1)
71                 .node(qName2)
72                 .build();
73         final ContainerNode data1 = Builders.containerBuilder()
74                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(qName1))
75                 .build();
76         final LeafNode<String> data2 = Builders.<String>leafBuilder()
77                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(qName2))
78                 .withValue("data")
79                 .build();
80         tx.put(LogicalDatastoreType.CONFIGURATION, yid1, data1);
81         tx.merge(LogicalDatastoreType.CONFIGURATION, yid2, data2);
82         //check, if no edit-config is called before submit
83         verify(rpc, never()).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME)), any());
84         tx.submit().get();
85         //check, if both edits are called
86         verify(rpc, times(2)).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME)), any());
87         //check, if unlock is called
88         verify(rpc).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME)), any());
89     }
90
91     private static SchemaContext parseYangStreams(final InputStream... streams) {
92         final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR
93                 .newBuild();
94         final SchemaContext schemaContext;
95         try {
96             schemaContext = reactor.buildEffective(ImmutableList.copyOf(streams));
97         } catch (final ReactorException e) {
98             throw new RuntimeException("Unable to build schema context from " + streams, e);
99         }
100         return schemaContext;
101     }
102 }