[ONOS-5884]YANG Serializer: Implement XML serializer.
Change-Id: Idffda88938d9c6c7b7c7814127a340bd2dc35039
diff --git a/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java
new file mode 100644
index 0000000..138d22d
--- /dev/null
+++ b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.onosproject.yang.YangModel;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangSchemaNode;
+import org.onosproject.yang.runtime.AppModuleInfo;
+import org.onosproject.yang.runtime.DefaultAppModuleInfo;
+import org.onosproject.yang.runtime.DefaultModelRegistrationParam;
+import org.onosproject.yang.runtime.ModelRegistrationParam;
+import org.onosproject.yang.runtime.YangModelRegistry;
+import org.onosproject.yang.runtime.ymrimpl.DefaultYangModelRegistry;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.deSerializeDataModel;
+import static org.onosproject.yang.compiler.plugin.utils.YangApacheUtils.processModuleId;
+import static org.onosproject.yang.compiler.plugin.utils.YangApacheUtils.processYangModel;
+import static org.onosproject.yang.compiler.utils.UtilConstants.TEMP;
+import static org.onosproject.yang.compiler.utils.io.impl.YangIoUtils.deleteDirectory;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.getInterfaceClassName;
+
+/**
+ * Represents mock bundle context. provides bundle context for YSR to do unit
+ * testing.
+ */
+public class MockYangSchemaNodeProvider {
+
+ private static final String FS = File.separator;
+ private static final String PATH = System.getProperty("user.dir") +
+ FS + "target" + FS + "classes" + FS;
+ private static final String SER_FILE_PATH = "yang" + FS + "resources" +
+ FS + "YangMetaData.ser";
+ private static final String META_PATH = PATH + SER_FILE_PATH;
+ private static final String TEMP_FOLDER_PATH = PATH + TEMP;
+ private YangModelRegistry reg = new DefaultYangModelRegistry();
+ private List<YangNode> nodes = new ArrayList<>();
+
+ /**
+ * Creates an instance of mock bundle context.
+ */
+ public MockYangSchemaNodeProvider() {
+ }
+
+ /**
+ * Process YANG schema node for a application.
+ */
+ public void processSchemaRegistry() {
+ try {
+ //Need to deserialize generated meta data file for unit tests.
+ Set<YangNode> appNode = deSerializeDataModel(META_PATH);
+ nodes.addAll(appNode);
+ reg.registerModel(prepareParam(nodes));
+ deleteDirectory(TEMP_FOLDER_PATH);
+ } catch (IOException e) {
+ }
+ }
+
+ /**
+ * Unregister given nodes from runtime service.
+ *
+ * @param nodes list of nodes
+ */
+ public void unRegister(List<YangNode> nodes) {
+ reg.unregisterModel(prepareParam(nodes));
+ }
+
+ /**
+ * Prepares model registration parameter.
+ *
+ * @param nodes list of nodes
+ * @return model registration parameter
+ */
+ private ModelRegistrationParam prepareParam(List<YangNode> nodes) {
+ //Process loading class file.
+ String appName;
+ ClassLoader classLoader = getClass().getClassLoader();
+
+ //Create model registration param.
+ ModelRegistrationParam.Builder b =
+ DefaultModelRegistrationParam.builder();
+
+ //create a new YANG model
+ YangModel model = processYangModel(META_PATH, nodes);
+ //set YANG model
+ b.setYangModel(model);
+
+ Iterator<YangNode> it = nodes.iterator();
+ while (it.hasNext()) {
+ YangSchemaNode node = it.next();
+
+ //If service class is not generated then use
+ // interface file to load this class.
+ appName = getInterfaceClassName(node);
+ Class<?> cls;
+ try {
+ cls = classLoader.loadClass(appName);
+ } catch (ClassNotFoundException e) {
+ continue;
+ }
+
+ //generate app info.
+ AppModuleInfo info = new DefaultAppModuleInfo(cls, null);
+ b.addAppModuleInfo(processModuleId((YangNode) node), info);
+ }
+ return b.build();
+ }
+
+ /**
+ * Returns schema registry.
+ *
+ * @return schema registry
+ */
+ public DefaultYangModelRegistry registry() {
+ return (DefaultYangModelRegistry) reg;
+ }
+}
diff --git a/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java
new file mode 100644
index 0000000..dfc8d06
--- /dev/null
+++ b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSerializerContext.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.onosproject.yang.model.SchemaContext;
+import org.onosproject.yang.runtime.Annotation;
+import org.onosproject.yang.runtime.DefaultAnnotation;
+import org.onosproject.yang.runtime.YangSerializerContext;
+import org.onosproject.yang.runtime.ymrimpl.DefaultYangModelRegistry;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Tests the default schema context provider methods.
+ */
+public class MockYangSerializerContext implements YangSerializerContext {
+
+ private static MockYangSchemaNodeProvider schemaProvider =
+ new MockYangSchemaNodeProvider();
+ private static final String NETCONF_NS =
+ "urn:ietf:params:xml:ns:netconf:base:1.0";
+ private static final String XMNLS_NC = "xmlns:xc";
+
+
+ @Override
+ public SchemaContext getContext() {
+ schemaProvider.processSchemaRegistry();
+ DefaultYangModelRegistry registry = schemaProvider.registry();
+ return registry;
+ }
+
+ @Override
+ public List<Annotation> getProtocolAnnotations() {
+ Annotation annotation = new DefaultAnnotation(XMNLS_NC, NETCONF_NS);
+ List<Annotation> protocolAnnotation = new LinkedList<>();
+ protocolAnnotation.add(annotation);
+ return protocolAnnotation;
+ }
+}
diff --git a/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/XmlSerializerTest.java b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/XmlSerializerTest.java
new file mode 100644
index 0000000..1f53ac5
--- /dev/null
+++ b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/XmlSerializerTest.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yang.serializers.xml;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.InnerNode;
+import org.onosproject.yang.model.LeafListKey;
+import org.onosproject.yang.model.LeafNode;
+import org.onosproject.yang.model.ListKey;
+import org.onosproject.yang.model.NodeKey;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.SchemaId;
+import org.onosproject.yang.runtime.AnnotatedNodeInfo;
+import org.onosproject.yang.runtime.Annotation;
+import org.onosproject.yang.runtime.CompositeData;
+import org.onosproject.yang.runtime.CompositeStream;
+import org.onosproject.yang.runtime.DefaultCompositeStream;
+import org.onosproject.yang.runtime.YangSerializer;
+import org.onosproject.yang.runtime.YangSerializerContext;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+/**
+ *
+ */
+public class XmlSerializerTest {
+
+ private static YangSerializerContext context;
+ private static YangSerializer xmlSerializer;
+
+ @BeforeClass
+ public static void prepare() {
+ context = new MockYangSerializerContext();
+ xmlSerializer = new XmlSerializer();
+ }
+
+ /**
+ * Validates data node in which XML element is of type YANG container.
+ */
+ @Test
+ public void testContainer() {
+ String path = "src/test/resources/testContainer.xml";
+
+ DefaultCompositeStream external =
+ new DefaultCompositeStream(null, parseInput(path));
+ CompositeData compositeData = xmlSerializer.decode(external, context);
+ DataNode rootNode = validateRootDataNode(compositeData.resourceData());
+ DataNode food = validateContainerDataNode(rootNode, "food", "yrt:food");
+ validateLeafDataNode(food, "p1", "yrt:food", "p1_value");
+ validateLeafListDataNode(food, "p2", "yrt:food", "p2_value");
+ validateLeafListDataNode(food, "p2", "yrt:food", "p2_value1");
+ DataNode c2 = validateContainerDataNode(rootNode, "c2", "yrt:food");
+ validateLeafDataNode(c2, "p3", "yrt:food", "p3_value");
+
+ // encode test
+ CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+ context);
+ InputStream inputStream = compositeStream.resourceData();
+ assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+ }
+
+ /**
+ * Validates data node in which XML element is of type YANG leaf.
+ */
+ @Test
+ public void testModuleLevelLeaf() {
+ String path = "src/test/resources/testModuleLevelLeaf.xml";
+
+ DefaultCompositeStream external =
+ new DefaultCompositeStream(null, parseInput(path));
+ CompositeData compositeData = xmlSerializer.decode(external, context);
+ DataNode rootNode = validateRootDataNode(compositeData.resourceData());
+ validateLeafDataNode(rootNode, "bool", "yrt:food", "true");
+
+ // encode test
+ CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+ context);
+ InputStream inputStream = compositeStream.resourceData();
+ assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+ }
+
+ /**
+ * Validates data node in which XML element is of type YANG list.
+ */
+ @Test
+ public void testListWithKeyleaves() {
+ String path = "src/test/resources/testListWithKeyleaves.xml";
+ DefaultCompositeStream external =
+ new DefaultCompositeStream(null, parseInput(path));
+ CompositeData compositeData = xmlSerializer.decode(external, context);
+ DataNode rootNode = validateRootDataNode(compositeData.resourceData());
+ List<String> keyNames = new LinkedList<>();
+ keyNames.add("k1");
+ keyNames.add("k2");
+ keyNames.add("k3");
+
+ List<String> keyNs = new LinkedList<>();
+ keyNs.add("yrt:list");
+ keyNs.add("yrt:list");
+ keyNs.add("yrt:list");
+
+ List<Object> values = new LinkedList<>();
+ values.add("k1_Value");
+ values.add("k2_Value");
+ values.add("k3_Value");
+
+ DataNode listl1 = validateListDataNode(rootNode, "l1", "yrt:list",
+ keyNames, keyNs, values);
+ validateLeafDataNode(listl1, "k1", "yrt:list", "k1_Value");
+ validateLeafDataNode(listl1, "k2", "yrt:list", "k2_Value");
+ validateLeafDataNode(listl1, "k3", "yrt:list", "k3_Value");
+ DataNode c1 = validateContainerDataNode(listl1, "c1", "yrt:list");
+ validateLeafDataNode(c1, "leaf_c1", "yrt:list", "l1_value");
+
+ values = new LinkedList<>();
+ values.add("k1_Value1");
+ values.add("k2_Value2");
+ values.add("k3_Value3");
+
+ DataNode listl2 = validateListDataNode(rootNode, "l1", "yrt:list",
+ keyNames, keyNs, values);
+ validateLeafDataNode(listl2, "k1", "yrt:list", "k1_Value1");
+ validateLeafDataNode(listl2, "k2", "yrt:list", "k2_Value2");
+ validateLeafDataNode(listl2, "k3", "yrt:list", "k3_Value3");
+ c1 = validateContainerDataNode(listl2, "c1", "yrt:list");
+ validateLeafDataNode(c1, "leaf_c1", "yrt:list", "l1_value1");
+
+ // encode test
+ CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+ context);
+ InputStream inputStream = compositeStream.resourceData();
+ assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+ }
+
+ /**
+ * Validates data node in which XML element is child of YANG
+ * choice-case.
+ */
+ @Test
+ public void testChoiceCase() {
+ String path = "src/test/resources/testChoiceCase.xml";
+
+ DefaultCompositeStream external =
+ new DefaultCompositeStream(null, parseInput(path));
+ CompositeData compositeData = xmlSerializer.decode(external, context);
+ DataNode rootNode = validateRootDataNode(compositeData.resourceData());
+ DataNode list1 = validateListDataNode(rootNode, "banana",
+ "yrt:choice-case", null, null, null);
+ validateLeafDataNode(list1, "l1", "yrt:choice-case", "value2");
+ DataNode coldDrink = validateContainerDataNode(rootNode, "cold-drink",
+ "yrt:choice-case");
+ validateLeafListDataNode(coldDrink, "flavor", "yrt:choice-case",
+ "value3");
+
+ // encode test
+ CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+ context);
+ InputStream inputStream = compositeStream.resourceData();
+ assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+ }
+
+ /**
+ * Validates data node in which XML element is of YANG augmented nodes.
+ */
+ @Test
+ public void testAugment() {
+ String path = "src/test/resources/testAugment.xml";
+
+ String uri = "urn:ietf:params:xml:ns:yang:yrt-ietf-network:networks/network/node";
+ DefaultCompositeStream external =
+ new DefaultCompositeStream(uri, parseInput(path));
+ CompositeData compositeData = xmlSerializer.decode(external, context);
+ ResourceData resourceData = compositeData.resourceData();
+ List<DataNode> dataNodes = resourceData.dataNodes();
+ DataNode dataNode = dataNodes.get(0);
+ SchemaId schemaId = dataNode.key().schemaId();
+ assertThat(schemaId.name(), is("t-point"));
+ assertThat(schemaId.namespace(), is("urn:ietf:params:xml:ns:yang:yrt-ietf-network-topology"));
+ validateLeafDataNode(dataNode, "tp-id",
+ "urn:ietf:params:xml:ns:yang:yrt-ietf-network-topology", "Stub");
+
+ // encode test
+ CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+ context);
+ InputStream inputStream = compositeStream.resourceData();
+ assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+ }
+
+ /**
+ * Validates data node in which XML element is child of YANG grouping.
+ */
+ @Test
+ public void testGroupingUsesDataNode() {
+ String path = "src/test/resources/testGroupingUses.xml";
+
+ String uri = "urn:ietf:params:xml:ns:yang:yrt-ietf-network:networks-state/network";
+ DefaultCompositeStream external =
+ new DefaultCompositeStream(uri, parseInput(path));
+ CompositeData compositeData = xmlSerializer.decode(external, context);
+ ResourceData resourceData = compositeData.resourceData();
+ List<DataNode> dataNodes = resourceData.dataNodes();
+ LeafNode dataNode = ((LeafNode) dataNodes.get(0));
+ SchemaId schemaId = dataNode.key().schemaId();
+ assertThat(schemaId.name(), is("network-ref"));
+ assertThat(schemaId.namespace(), is("urn:ietf:params:xml:ns:yang:yrt-ietf-network"));
+ assertThat(dataNode.value().toString(), is("abc"));
+
+ // encode test
+ CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+ context);
+ InputStream inputStream = compositeStream.resourceData();
+ assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+ }
+
+ /**
+ * Validates whether XML attributes is converted to annotations.
+ */
+ @Test
+ public void testXmlAttributes() {
+ String path = "src/test/resources/testXmlAttributes.xml";
+ String namespace = "http://example.com/schema/1.2/config";
+
+ DefaultCompositeStream external =
+ new DefaultCompositeStream(null, parseInput(path));
+ CompositeData compositeData = xmlSerializer.decode(external, context);
+ DataNode rootNode = validateRootDataNode(compositeData.resourceData());
+ DataNode top = validateContainerDataNode(rootNode, "top", namespace);
+ DataNode interfaceDn = validateContainerDataNode(top, "interface",
+ namespace);
+ validateLeafDataNode(interfaceDn, "name", namespace, "Ethernet0/0");
+ validateLeafDataNode(interfaceDn, "mtu", namespace, "1500");
+ DataNode address = validateContainerDataNode(interfaceDn, "address",
+ namespace);
+ validateLeafDataNode(address, "name", namespace, "192.0.2.4");
+ validateLeafDataNode(address, "prefix-length", namespace, "24");
+
+ List<AnnotatedNodeInfo> annotatedNodeInfos = compositeData
+ .annotatedNodesInfo();
+ AnnotatedNodeInfo annotatedNodeInfo = annotatedNodeInfos.get(0);
+ List<Annotation> annotationList = annotatedNodeInfo.annotations();
+ Annotation annotation = annotationList.get(0);
+ assertThat(annotation.name(), is("xc:operation"));
+ assertThat(annotation.value(), is("replace"));
+
+ // encode test
+ CompositeStream compositeStream = xmlSerializer.encode(compositeData,
+ context);
+ InputStream inputStream = compositeStream.resourceData();
+ assertThat(convertInputStreamToString(inputStream), is(parseXml(path)));
+ }
+
+ /**
+ * Validates and returns container data node.
+ *
+ * @param parent data node holding container
+ * @param name name of the container
+ * @param namespace namespace of the container
+ * @return container data node
+ */
+ private static DataNode validateContainerDataNode(DataNode parent,
+ String name,
+ String namespace) {
+ Map<NodeKey, DataNode> childNodes = ((InnerNode) parent).childNodes();
+ NodeKey key = NodeKey.builder().schemaId(name, namespace).build();
+ DataNode dataNode = childNodes.get(key);
+ SchemaId schemaId = dataNode.key().schemaId();
+ assertThat(schemaId.name(), is(name));
+ assertThat(schemaId.namespace(), is(namespace));
+ return dataNode;
+ }
+
+ /**
+ * Validates and returns list data node.
+ *
+ * @param parent data node holding list
+ * @param name name of the list
+ * @param namespace namespace of the list
+ * @param keynames list of key leaf names
+ * @param keyNs list of key leaf namespace
+ * @param keyVal list of key leaf values
+ * @return list data node
+ */
+ private static DataNode validateListDataNode(DataNode parent,
+ String name, String namespace,
+ List<String> keynames,
+ List<String> keyNs,
+ List<Object> keyVal) {
+ Map<NodeKey, DataNode> childNodes = ((InnerNode) parent).childNodes();
+ NodeKey key = NodeKey.builder().schemaId(name, namespace).build();
+ DataNode dataNode;
+ if (keynames != null && !keynames.isEmpty()) {
+ ListKey.ListKeyBuilder listKeyBldr = new ListKey.ListKeyBuilder();
+ listKeyBldr.schemaId(key.schemaId());
+ for (int i = 0; i < keynames.size(); i++) {
+ listKeyBldr.addKeyLeaf(keynames.get(i), keyNs.get(i),
+ keyVal.get(i));
+ }
+ dataNode = childNodes.get(listKeyBldr.build());
+ } else {
+ dataNode = childNodes.get(key);
+ }
+ SchemaId schemaId = dataNode.key().schemaId();
+ assertThat(schemaId.name(), is(name));
+ assertThat(schemaId.namespace(), is(namespace));
+ return dataNode;
+ }
+
+ /**
+ * Validates leaf data node.
+ *
+ * @param parent data node holding leaf
+ * @param name name of the leaf
+ * @param namespace namespace of the leaf
+ * @param value leaf value
+ */
+ private static void validateLeafDataNode(DataNode parent,
+ String name, String namespace,
+ Object value) {
+ Map<NodeKey, DataNode> childNodes = ((InnerNode) parent).childNodes();
+ NodeKey key = NodeKey.builder().schemaId(name, namespace).build();
+ LeafNode dataNode = ((LeafNode) childNodes.get(key));
+ SchemaId schemaId = dataNode.key().schemaId();
+ assertThat(schemaId.name(), is(name));
+ assertThat(schemaId.namespace(), is(namespace));
+ assertThat(dataNode.value().toString(), is(value));
+ }
+
+ /**
+ * Validates leaf-list data node.
+ *
+ * @param parent data node holding leaf-list
+ * @param name name of the leaf-list
+ * @param namespace namespace of the leaf-list
+ * @param value leaf-list value
+ */
+ private static void validateLeafListDataNode(DataNode parent,
+ String name, String namespace,
+ Object value) {
+ Map<NodeKey, DataNode> childNodes = ((InnerNode) parent).childNodes();
+ NodeKey key = NodeKey.builder().schemaId(name, namespace).build();
+ LeafListKey.LeafListKeyBuilder leafListBldr =
+ new LeafListKey.LeafListKeyBuilder();
+ leafListBldr.schemaId(key.schemaId());
+ leafListBldr.value(value);
+ DataNode leafListNode = childNodes.get(leafListBldr.build());
+ SchemaId schemaId = leafListNode.key().schemaId();
+ assertThat(schemaId.name(), is(name));
+ assertThat(schemaId.namespace(), is(namespace));
+ assertThat(((LeafNode) leafListNode).value().toString(), is(value));
+ }
+
+ /**
+ * Validates root data node.
+ *
+ * @param resourceData resource data which holds data node
+ * @return root data node
+ */
+ private static DataNode validateRootDataNode(ResourceData resourceData) {
+ List<DataNode> dataNodes = resourceData.dataNodes();
+ DataNode rootNode = dataNodes.get(0);
+ SchemaId rootSchemaId = rootNode.key().schemaId();
+ assertThat(rootSchemaId.name(), is("/"));
+ return rootNode;
+ }
+
+ /**
+ * Reads XML contents from file path and returns input stream.
+ *
+ * @param path path of XML file
+ * @return input stream
+ */
+ private static InputStream parseInput(String path) {
+ String temp;
+ StringBuilder sb = new StringBuilder();
+ try (BufferedReader br = new BufferedReader(new FileReader(path))) {
+ while ((temp = br.readLine()) != null) {
+ sb.append(temp);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return IOUtils.toInputStream(sb);
+ }
+
+ /**
+ * Reads XML contents from file path and returns input stream.
+ *
+ * @param path path of XML file
+ * @return input stream
+ */
+ private static String parseXml(String path) {
+ String temp;
+ StringBuilder sb = new StringBuilder();
+ try (BufferedReader br = new BufferedReader(new FileReader(path))) {
+ while ((temp = br.readLine()) != null) {
+ sb.append(temp);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Converts input stream to string format.
+ *
+ * @param inputStream input stream of xml
+ * @return XML string
+ */
+ private static String convertInputStreamToString(InputStream inputStream) {
+ BufferedReader br;
+ StringBuilder sb = new StringBuilder();
+ String xmlData;
+ br = new BufferedReader(new InputStreamReader(inputStream));
+ try {
+ while ((xmlData = br.readLine()) != null) {
+ sb.append(xmlData);
+ }
+ } catch (IOException e) {
+ throw new XmlSerializerException(e.getMessage());
+ }
+ return sb.toString();
+ }
+}
diff --git a/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/package-info.java b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/package-info.java
new file mode 100644
index 0000000..43b4abc
--- /dev/null
+++ b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * The XML serializer implementation of the YangSerializer interface.
+ */
+package org.onosproject.yang.serializers.xml;
diff --git a/serializers/xml/src/test/resources/testAugment.xml b/serializers/xml/src/test/resources/testAugment.xml
new file mode 100644
index 0000000..4c883f6
--- /dev/null
+++ b/serializers/xml/src/test/resources/testAugment.xml
@@ -0,0 +1,3 @@
+<t-point xmlns="urn:ietf:params:xml:ns:yang:yrt-ietf-network-topology">
+<tp-id>Stub</tp-id>
+</t-point>
\ No newline at end of file
diff --git a/serializers/xml/src/test/resources/testChoiceCase.xml b/serializers/xml/src/test/resources/testChoiceCase.xml
new file mode 100644
index 0000000..22590a1
--- /dev/null
+++ b/serializers/xml/src/test/resources/testChoiceCase.xml
@@ -0,0 +1,6 @@
+<banana xmlns="yrt:choice-case">
+<l1>value2</l1>
+</banana>
+<cold-drink xmlns="yrt:choice-case">
+<flavor>value3</flavor>
+</cold-drink>
diff --git a/serializers/xml/src/test/resources/testContainer.xml b/serializers/xml/src/test/resources/testContainer.xml
new file mode 100644
index 0000000..ee679b8
--- /dev/null
+++ b/serializers/xml/src/test/resources/testContainer.xml
@@ -0,0 +1,8 @@
+<food xmlns="yrt:food">
+<p1>p1_value</p1>
+<p2>p2_value</p2>
+<p2>p2_value1</p2>
+</food>
+<c2 xmlns="yrt:food">
+<p3>p3_value</p3>
+</c2>
\ No newline at end of file
diff --git a/serializers/xml/src/test/resources/testGroupingUses.xml b/serializers/xml/src/test/resources/testGroupingUses.xml
new file mode 100644
index 0000000..45d3d05
--- /dev/null
+++ b/serializers/xml/src/test/resources/testGroupingUses.xml
@@ -0,0 +1,2 @@
+<network-ref xmlns="urn:ietf:params:xml:ns:yang:yrt-ietf-network">abc
+</network-ref>
\ No newline at end of file
diff --git a/serializers/xml/src/test/resources/testListWithKeyleaves.xml b/serializers/xml/src/test/resources/testListWithKeyleaves.xml
new file mode 100644
index 0000000..1f9616a
--- /dev/null
+++ b/serializers/xml/src/test/resources/testListWithKeyleaves.xml
@@ -0,0 +1,16 @@
+<l1 xmlns="yrt:list" operation="replace">
+<k1>k1_Value</k1>
+<k2>k2_Value</k2>
+<k3>k3_Value</k3>
+<c1>
+<leaf_c1>l1_value</leaf_c1>
+</c1>
+</l1>
+<l1 xmlns="yrt:list" operation="replace">
+<k1>k1_Value1</k1>
+<k2>k2_Value2</k2>
+<k3>k3_Value3</k3>
+<c1>
+<leaf_c1>l1_value1</leaf_c1>
+</c1>
+</l1>
diff --git a/serializers/xml/src/test/resources/testModuleLevelLeaf.xml b/serializers/xml/src/test/resources/testModuleLevelLeaf.xml
new file mode 100644
index 0000000..13da6e6
--- /dev/null
+++ b/serializers/xml/src/test/resources/testModuleLevelLeaf.xml
@@ -0,0 +1,2 @@
+<bool xmlns="yrt:food">true</bool>
+<boolean xmlns="yrt:food">true</boolean>
\ No newline at end of file
diff --git a/serializers/xml/src/test/resources/testMultipleLevelAugment.xml b/serializers/xml/src/test/resources/testMultipleLevelAugment.xml
new file mode 100644
index 0000000..ab31d06
--- /dev/null
+++ b/serializers/xml/src/test/resources/testMultipleLevelAugment.xml
@@ -0,0 +1,6 @@
+<interface xmlns="ser.ospf" operation="replace">
+<area-type>Stub</area-type>
+</interface>
+<statistics xmlns="ser.ospf" operation="replace">
+<spf-runs-count>3</spf-runs-count>
+</statistics>
\ No newline at end of file
diff --git a/serializers/xml/src/test/resources/testXmlAttributes.xml b/serializers/xml/src/test/resources/testXmlAttributes.xml
new file mode 100644
index 0000000..0ca9a71
--- /dev/null
+++ b/serializers/xml/src/test/resources/testXmlAttributes.xml
@@ -0,0 +1,10 @@
+<top xmlns="http://example.com/schema/1.2/config">
+<interface xc:operation="replace">
+<name>Ethernet0/0</name>
+<mtu>1500</mtu>
+<address>
+<name>192.0.2.4</name>
+<prefix-length>24</prefix-length>
+</address>
+</interface>
+</top>
\ No newline at end of file