Fix YANG patch request for augmented element
[netconf.git] / restconf / restconf-nb-rfc8040 / src / test / java / org / opendaylight / restconf / nb / rfc8040 / jersey / providers / patch / XmlPatchBodyReaderTest.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 package org.opendaylight.restconf.nb.rfc8040.jersey.providers.patch;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertThrows;
12
13 import java.io.ByteArrayInputStream;
14 import java.io.InputStream;
15 import java.nio.charset.StandardCharsets;
16 import javax.ws.rs.core.MediaType;
17 import org.junit.BeforeClass;
18 import org.junit.Test;
19 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
20 import org.opendaylight.restconf.nb.rfc8040.jersey.providers.test.AbstractBodyReaderTest;
21 import org.opendaylight.restconf.nb.rfc8040.jersey.providers.test.XmlBodyReaderTest;
22 import org.opendaylight.yangtools.yang.common.ErrorTag;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
24 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
25 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
26 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
27
28 public class XmlPatchBodyReaderTest extends AbstractBodyReaderTest {
29     private static EffectiveModelContext schemaContext;
30
31     private final XmlPatchBodyReader xmlToPatchBodyReader;
32
33     public XmlPatchBodyReaderTest() throws Exception {
34         super(schemaContext);
35         xmlToPatchBodyReader = new XmlPatchBodyReader(schemaContextHandler, mountPointService);
36     }
37
38     @Override
39     protected MediaType getMediaType() {
40         return new MediaType(MediaType.APPLICATION_XML, null);
41     }
42
43     @BeforeClass
44     public static void initialization() {
45         schemaContext = schemaContextLoader("/instanceidentifier/yang", schemaContext);
46     }
47
48     @Test
49     public void moduleDataTest() throws Exception {
50         mockBodyReader("instance-identifier-patch-module:patch-cont/my-list1=leaf1", xmlToPatchBodyReader, false);
51         checkPatchContext(xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null,
52             XmlBodyReaderTest.class.getResourceAsStream("/instanceidentifier/xml/xmlPATCHdata.xml")));
53     }
54
55     /**
56      * Test trying to use Patch create operation which requires value without value. Error code 400 should be returned.
57      */
58     @Test
59     public void moduleDataValueMissingNegativeTest() throws Exception {
60         mockBodyReader("instance-identifier-patch-module:patch-cont/my-list1=leaf1", xmlToPatchBodyReader, false);
61         final InputStream inputStream = XmlBodyReaderTest.class.getResourceAsStream(
62             "/instanceidentifier/xml/xmlPATCHdataValueMissing.xml");
63         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
64             () -> xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream));
65         assertEquals(ErrorTag.MALFORMED_MESSAGE, ex.getErrors().get(0).getErrorTag());
66     }
67
68     /**
69      * Test trying to use value with Patch delete operation which does not support value. Error code 400 should be
70      * returned.
71      */
72     @Test
73     public void moduleDataNotValueNotSupportedNegativeTest() throws Exception {
74         mockBodyReader("instance-identifier-patch-module:patch-cont/my-list1=leaf1", xmlToPatchBodyReader, false);
75         final InputStream inputStream = XmlBodyReaderTest.class.getResourceAsStream(
76             "/instanceidentifier/xml/xmlPATCHdataValueNotSupported.xml");
77         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
78             () -> xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream));
79         assertEquals(ErrorTag.MALFORMED_MESSAGE, ex.getErrors().get(0).getErrorTag());
80     }
81
82     /**
83      * Test of Yang Patch with absolute target path.
84      */
85     @Test
86     public void moduleDataAbsoluteTargetPathTest() throws Exception {
87         mockBodyReader("", xmlToPatchBodyReader, false);
88         checkPatchContext(xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null,
89             XmlBodyReaderTest.class.getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataAbsoluteTargetPath.xml")));
90     }
91
92     /**
93      * Test using Patch when target is completely specified in request URI and thus target leaf contains only '/' sign.
94      */
95     @Test
96     public void modulePatchCompleteTargetInURITest() throws Exception {
97         mockBodyReader("instance-identifier-patch-module:patch-cont", xmlToPatchBodyReader, false);
98         checkPatchContext(xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null,
99             XmlBodyReaderTest.class.getResourceAsStream(
100                 "/instanceidentifier/xml/xmlPATCHdataCompleteTargetInURI.xml")));
101     }
102
103     /**
104      * Test of Yang Patch merge operation on list. Test consists of two edit operations - replace and merge.
105      */
106     @Test
107     public void moduleDataMergeOperationOnListTest() throws Exception {
108         mockBodyReader("instance-identifier-patch-module:patch-cont/my-list1=leaf1", xmlToPatchBodyReader, false);
109         final InputStream inputStream = XmlBodyReaderTest.class.getResourceAsStream(
110             "/instanceidentifier/xml/xmlPATCHdataMergeOperationOnList.xml");
111         checkPatchContext(xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream));
112     }
113
114     /**
115      * Test of Yang Patch merge operation on container. Test consists of two edit operations - create and merge.
116      */
117     @Test
118     public void moduleDataMergeOperationOnContainerTest() throws Exception {
119         mockBodyReader("instance-identifier-patch-module:patch-cont", xmlToPatchBodyReader, false);
120         final InputStream inputStream = XmlBodyReaderTest.class
121                 .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataMergeOperationOnContainer.xml");
122         checkPatchContext(xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream));
123     }
124
125     /**
126      * Test of Yang Patch on the top-level container with empty URI for data root.
127      */
128     @Test
129     public void modulePatchTargetTopLevelContainerWithEmptyURITest() throws Exception {
130         mockBodyReader("", xmlToPatchBodyReader, false);
131         final InputStream inputStream = XmlBodyReaderTest.class
132                 .getResourceAsStream("/instanceidentifier/xml/xmlPATCHTargetTopLevelContainerWithEmptyURI.xml");
133         checkPatchContext(xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream));
134     }
135
136     /**
137      * Test of Yang Patch on the top augmented element.
138      */
139     @Test
140     public void moduleTargetTopLevelAugmentedContainerTest() throws Exception {
141         mockBodyReader("", xmlToPatchBodyReader, false);
142         final var inputStream = new ByteArrayInputStream((
143             "<yang-patch xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-patch\">\n"
144                 + "    <patch-id>test-patch</patch-id>\n"
145                 + "    <comment>This test patch for augmented element</comment>\n"
146                 + "    <edit>\n"
147                 + "        <edit-id>edit1</edit-id>\n"
148                 + "        <operation>replace</operation>\n"
149                 + "        <target>/test-m:container-root/test-m:container-lvl1/test-m-aug:container-aug</target>\n"
150                 + "        <value>\n"
151                 + "            <container-aug xmlns=\"test-ns-aug\">\n"
152                 + "                <leaf-aug>data</leaf-aug>\n"
153                 + "            </container-aug>\n"
154                 + "        </value>\n"
155                 + "    </edit>\n"
156                 + "</yang-patch>").getBytes(StandardCharsets.UTF_8));
157         final var expectedData = Builders.containerBuilder()
158                 .withNodeIdentifier(new NodeIdentifier(CONT_AUG_QNAME))
159                 .withChild(ImmutableNodes.leafNode(LEAF_AUG_QNAME, "data"))
160                 .build();
161         final var returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
162         checkPatchContext(returnValue);
163         final var data = returnValue.getData().get(0).getNode();
164         assertEquals(CONT_AUG_QNAME, data.getIdentifier().getNodeType());
165         assertEquals(expectedData, data);
166     }
167 }