X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fconfig-netconf-connector%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Fconfignetconfconnector%2FNetconfMappingTest.java;h=9511673ea40781446c4134f02d3b1defbe47353a;hp=296b224fffbbc2e33fccc898dd78dcd204267d46;hb=8720a3f3498bbc6fab675431f4200d26641a8ec8;hpb=24feaa3333de6eadfc99a63cce0f95479e3b5f96 diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java index 296b224fff..54b15a85b2 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java @@ -8,108 +8,129 @@ package org.opendaylight.controller.netconf.confignetconfconnector; +import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElement; +import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText; +import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToElement; + import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; +import javax.xml.parsers.ParserConfigurationException; +import org.custommonkey.xmlunit.AbstractNodeTester; +import org.custommonkey.xmlunit.NodeTest; +import org.custommonkey.xmlunit.NodeTestException; +import org.custommonkey.xmlunit.NodeTester; +import org.custommonkey.xmlunit.XMLAssert; +import org.custommonkey.xmlunit.XMLUnit; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.matchers.JUnitMatchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.opendaylight.controller.config.api.ModuleIdentifier; -import org.opendaylight.controller.config.api.runtime.RootRuntimeBeanRegistrator; +import org.opendaylight.controller.config.api.ConflictingVersionException; +import org.opendaylight.controller.config.api.ValidationException; +import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface; +import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; -import org.opendaylight.controller.config.manager.impl.jmx.RootRuntimeBeanRegistratorImpl; import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; -import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot; -import org.opendaylight.controller.config.yang.store.impl.MbeParser; -import org.opendaylight.controller.config.yang.test.impl.Asdf; import org.opendaylight.controller.config.yang.test.impl.ComplexDtoBInner; import org.opendaylight.controller.config.yang.test.impl.ComplexList; import org.opendaylight.controller.config.yang.test.impl.Deep; -import org.opendaylight.controller.config.yang.test.impl.Deep2; -import org.opendaylight.controller.config.yang.test.impl.Deep3; -import org.opendaylight.controller.config.yang.test.impl.Deep4; import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory; import org.opendaylight.controller.config.yang.test.impl.DtoAInner; import org.opendaylight.controller.config.yang.test.impl.DtoAInnerInner; import org.opendaylight.controller.config.yang.test.impl.DtoC; import org.opendaylight.controller.config.yang.test.impl.DtoD; -import org.opendaylight.controller.config.yang.test.impl.InnerInnerRunningDataRuntimeMXBean; -import org.opendaylight.controller.config.yang.test.impl.InnerRunningDataAdditionalRuntimeMXBean; -import org.opendaylight.controller.config.yang.test.impl.InnerRunningDataRuntimeMXBean; -import org.opendaylight.controller.config.yang.test.impl.InnerRunningDataRuntimeRegistration; +import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFactory; import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory; import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMXBean; -import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplRuntimeMXBean; -import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplRuntimeRegistration; -import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplRuntimeRegistrator; -import org.opendaylight.controller.config.yang.test.impl.NotStateBean; -import org.opendaylight.controller.config.yang.test.impl.NotStateBeanInternal; import org.opendaylight.controller.config.yang.test.impl.Peers; -import org.opendaylight.controller.config.yang.test.impl.RetValContainer; -import org.opendaylight.controller.config.yang.test.impl.RetValList; import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; -import org.opendaylight.controller.netconf.api.NetconfOperationRouter; import org.opendaylight.controller.netconf.confignetconfconnector.operations.Commit; import org.opendaylight.controller.netconf.confignetconfconnector.operations.DiscardChanges; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig; import org.opendaylight.controller.netconf.confignetconfconnector.operations.get.Get; import org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig.GetConfig; import org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc.RuntimeRpc; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreServiceImpl; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession; +import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter; +import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution; import org.opendaylight.controller.netconf.util.test.XmlFileLoader; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity2; +import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry; +import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; +import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.w3c.dom.traversal.DocumentTraversal; import org.xml.sax.SAXException; -import javax.management.InstanceAlreadyExistsException; -import javax.management.ObjectName; -import javax.xml.parsers.ParserConfigurationException; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - public class NetconfMappingTest extends AbstractConfigTest { private static final Logger logger = LoggerFactory.getLogger(NetconfMappingTest.class); - private static final String INSTANCE_NAME = "test1"; + private static final String INSTANCE_NAME = "instance-from-code"; private static final String NETCONF_SESSION_ID = "foo"; + private static final String TEST_NAMESPACE= "urn:opendaylight:params:xml:ns:yang:controller:test:impl"; private NetconfTestImplModuleFactory factory; private DepTestImplModuleFactory factory2; + private IdentityTestModuleFactory factory3; @Mock YangStoreSnapshot yangStoreSnapshot; @Mock NetconfOperationRouter netconfOperationRouter; + @Mock + NetconfOperationServiceSnapshotImpl netconfOperationServiceSnapshot; private TransactionProvider transactionProvider; @@ -117,31 +138,188 @@ public class NetconfMappingTest extends AbstractConfigTest { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); doReturn(getMbes()).when(this.yangStoreSnapshot).getModuleMXBeanEntryMap(); + doReturn(getModules()).when(this.yangStoreSnapshot).getModules(); + doNothing().when(netconfOperationServiceSnapshot).close(); + this.factory = new NetconfTestImplModuleFactory(); this.factory2 = new DepTestImplModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(this.factory, this.factory2)); + this.factory3 = new IdentityTestModuleFactory(); + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, this.factory, this.factory2, + this.factory3)); transactionProvider = new TransactionProvider(this.configRegistryClient, NETCONF_SESSION_ID); } - private ObjectName createModule(final String instanceName) throws InstanceAlreadyExistsException { + private ObjectName createModule(final String instanceName) throws InstanceAlreadyExistsException, InstanceNotFoundException, URISyntaxException, ValidationException, ConflictingVersionException { final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction(); final ObjectName on = transaction.createModule(this.factory.getImplementationName(), instanceName); final NetconfTestImplModuleMXBean mxBean = transaction.newMXBeanProxy(on, NetconfTestImplModuleMXBean.class); - setModule(mxBean, transaction); + setModule(mxBean, transaction, instanceName + "_dep"); + + int i = 1; + for (Class sInterface : factory.getImplementedServiceIntefaces()) { + ServiceInterfaceAnnotation annotation = sInterface.getAnnotation(ServiceInterfaceAnnotation.class); + transaction.saveServiceReference( + transaction.getServiceInterfaceName(annotation.namespace(), annotation.localName()), "ref_from_code_to_" + instanceName + "_" + i++, + on); + } transaction.commit(); return on; } + @Test + public void testIdentityRefs() throws Exception { + edit("netconfMessages/editConfig_identities.xml"); + + commit(); + getConfigRunning(); + } + + @Override + protected CodecRegistry getCodecRegistry() { + IdentityCodec idCodec = mock(IdentityCodec.class); + doReturn(TestIdentity1.class).when(idCodec).deserialize(TestIdentity1.QNAME); + doReturn(TestIdentity2.class).when(idCodec).deserialize(TestIdentity2.QNAME); + + CodecRegistry codecReg = super.getCodecRegistry(); + doReturn(idCodec).when(codecReg).getIdentityCodec(); + return codecReg; + } + + @Test + public void testServicePersistance() throws Exception { + createModule(INSTANCE_NAME); + + edit("netconfMessages/editConfig.xml"); + Document config = getConfigCandidate(); + assertCorrectServiceNames(config, Sets.newHashSet("user_to_instance_from_code", "ref_dep_user", + "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1", + "ref_from_code_to_instance-from-code_1")); + + + edit("netconfMessages/editConfig_addServiceName.xml"); + config = getConfigCandidate(); + assertCorrectServiceNames(config, Sets.newHashSet("user_to_instance_from_code", "ref_dep_user", + "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1", + "ref_from_code_to_instance-from-code_1", "ref_dep_user_another")); + + edit("netconfMessages/editConfig_addServiceNameOnTest.xml"); + config = getConfigCandidate(); + assertCorrectServiceNames(config, Sets.newHashSet("user_to_instance_from_code", "ref_dep_user", + "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1", + "ref_from_code_to_instance-from-code_1", "ref_dep_user_another")); + + commit(); + config = getConfigRunning(); + assertCorrectRefNamesForDependencies(config); + assertCorrectServiceNames(config, Sets.newHashSet("user_to_instance_from_code", "ref_dep_user", + "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1", + "ref_from_code_to_instance-from-code_1", "ref_dep_user_another")); + + edit("netconfMessages/editConfig_replace_default.xml"); + config = getConfigCandidate(); + assertCorrectServiceNames(config, Collections.emptySet()); + + edit("netconfMessages/editConfig_remove.xml"); + config = getConfigCandidate(); + assertCorrectServiceNames(config, Collections.emptySet()); + + commit(); + config = getConfigCandidate(); + assertCorrectServiceNames(config, Collections.emptySet()); + + } + + private void assertCorrectRefNamesForDependencies(Document config) throws NodeTestException { + NodeList modulesList = config.getElementsByTagName("modules"); + assertEquals(1, modulesList.getLength()); + + NodeTest nt = new NodeTest((DocumentTraversal) config, modulesList.item(0)); + NodeTester tester = new AbstractNodeTester() { + private int defaultRefNameCount = 0; + private int userRefNameCount = 0; + + @Override + public void testText(Text text) throws NodeTestException { + if(text.getData().equals("ref_dep2")) { + defaultRefNameCount++; + } else if(text.getData().equals("ref_dep_user_two")) { + userRefNameCount++; + } + } + + @Override + public void noMoreNodes(NodeTest forTest) throws NodeTestException { + assertEquals(0, defaultRefNameCount); + assertEquals(2, userRefNameCount); + } + }; + nt.performTest(tester, Node.TEXT_NODE); + } + + private void assertCorrectServiceNames(Document configCandidate, Set refNames) throws NodeTestException { + final Set refNames2 = new HashSet<>(refNames); + NodeList servicesNodes = configCandidate.getElementsByTagName("services"); + assertEquals(1, servicesNodes.getLength()); + + NodeTest nt = new NodeTest((DocumentTraversal) configCandidate, servicesNodes.item(0)); + NodeTester tester = new AbstractNodeTester() { + + @Override + public void testElement(Element element) throws NodeTestException { + if(element.getNodeName() != null) { + if(element.getNodeName().equals("name")) { + String elmText = element.getTextContent(); + if(refNames2.contains(elmText)) { + refNames2.remove(elmText); + } else { + throw new NodeTestException("Unexpected services defined: " + elmText); + } + } + } + } + + @Override + public void noMoreNodes(NodeTest forTest) throws NodeTestException { + assertEquals(Collections.emptySet(), refNames2); + assertTrue(refNames2.toString(), refNames2.isEmpty()); + } + }; + nt.performTest(tester, Node.ELEMENT_NODE); + } + + @Test + public void testConfigNetconfUnionTypes() throws Exception { + + createModule(INSTANCE_NAME); + + edit("netconfMessages/editConfig.xml"); + commit(); + Document response = getConfigRunning(); + Element ipElement = readXmlToElement("0:0:0:0:0:0:0:1"); + assertContainsElement(response, readXmlToElement("0:0:0:0:0:0:0:1")); + + assertContainsElement(response, readXmlToElement("456")); + + + edit("netconfMessages/editConfig_setUnions.xml"); + commit(); + response = getConfigRunning(); + assertContainsElement(response, readXmlToElement("127.1.2.3")); + assertContainsElement(response, readXmlToElement("randomStringForUnion")); + + } + @Test public void testConfigNetconf() throws Exception { createModule(INSTANCE_NAME); edit("netconfMessages/editConfig.xml"); - checkBinaryLeafEdited(getConfigCandidate()); + Document configCandidate = getConfigCandidate(); + checkBinaryLeafEdited(configCandidate); // default-operation:none, should not affect binary leaf @@ -150,38 +328,42 @@ public class NetconfMappingTest extends AbstractConfigTest { // check after edit commit(); - Element response = getConfigRunning(); + Document response = getConfigRunning(); checkBinaryLeafEdited(response); checkTypeConfigAttribute(response); + checkTypedefs(response); + checkTestingDeps(response); + checkEnum(response); + checkBigDecimal(response); edit("netconfMessages/editConfig_remove.xml"); commit(); - response = getConfigCandidate(); - final String responseFromCandidate = XmlUtil.toString(response).replaceAll("\\s+", ""); - // System.out.println(responseFromCandidate); - response = getConfigRunning(); - final String responseFromRunning = XmlUtil.toString(response).replaceAll("\\s+", ""); - // System.out.println(responseFromRunning); - assertEquals(responseFromCandidate, responseFromRunning); - - final String expectedResult = XmlFileLoader.fileToString("netconfMessages/editConfig_expectedResult.xml") - .replaceAll("\\s+", ""); + assertXMLEqual(getConfigCandidate(), getConfigRunning()); - assertEquals(expectedResult, responseFromRunning); - assertEquals(expectedResult, responseFromCandidate); + final Document expectedResult = XmlFileLoader.xmlFileToDocument("netconfMessages/editConfig_expectedResult.xml"); + XMLUnit.setIgnoreWhitespace(true); + assertXMLEqual(expectedResult, getConfigRunning()); + assertXMLEqual(expectedResult, getConfigCandidate()); edit("netconfMessages/editConfig_none.xml"); - doNothing().when(netconfOperationRouter).close(); closeSession(); - verify(netconfOperationRouter).close(); + verify(netconfOperationServiceSnapshot).close(); verifyNoMoreInteractions(netconfOperationRouter); + verifyNoMoreInteractions(netconfOperationServiceSnapshot); + } + + private void checkBigDecimal(Document response) throws NodeTestException, SAXException, IOException { + assertContainsElement(response, readXmlToElement("2.58")); + // Default + assertContainsElement(response, readXmlToElement("2.00")); + } private void closeSession() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException { - DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID); + DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID, netconfOperationServiceSnapshot); executeOp(closeOp, "netconfMessages/closeSession.xml"); } @@ -197,20 +379,21 @@ public class NetconfMappingTest extends AbstractConfigTest { executeOp(commitOp, "netconfMessages/commit.xml"); } - private Element getConfigCandidate() throws ParserConfigurationException, SAXException, IOException, + private Document getConfigCandidate() throws ParserConfigurationException, SAXException, IOException, NetconfDocumentedException { GetConfig getConfigOp = new GetConfig(yangStoreSnapshot, Optional. absent(), transactionProvider, configRegistryClient, NETCONF_SESSION_ID); return executeOp(getConfigOp, "netconfMessages/getConfig_candidate.xml"); } - private Element getConfigRunning() throws ParserConfigurationException, SAXException, IOException, + private Document getConfigRunning() throws ParserConfigurationException, SAXException, IOException, NetconfDocumentedException { GetConfig getConfigOp = new GetConfig(yangStoreSnapshot, Optional. absent(), transactionProvider, configRegistryClient, NETCONF_SESSION_ID); return executeOp(getConfigOp, "netconfMessages/getConfig.xml"); } + @Ignore("second edit message corrupted") @Test(expected = NetconfDocumentedException.class) public void testConfigNetconfReplaceDefaultEx() throws Exception { @@ -227,7 +410,7 @@ public class NetconfMappingTest extends AbstractConfigTest { edit("netconfMessages/editConfig.xml"); commit(); - Element response = getConfigRunning(); + Document response = getConfigRunning(); final int allInstances = response.getElementsByTagName("module").getLength(); edit("netconfMessages/editConfig_replace_default.xml"); @@ -246,14 +429,9 @@ public class NetconfMappingTest extends AbstractConfigTest { edit("netconfMessages/namespaces/editConfig_sameAttrDifferentNamespaces.xml"); } catch (NetconfDocumentedException e) { String message = e.getMessage(); - assertThat(message, - JUnitMatchers - .containsString("Element simple-long-2 present multiple times with different namespaces")); - assertThat(message, - JUnitMatchers.containsString("urn:opendaylight:params:xml:ns:yang:controller:test:impl")); - assertThat(message, - JUnitMatchers - .containsString(XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG)); + assertContainsString(message, "Element simple-long-2 present multiple times with different namespaces"); + assertContainsString(message, TEST_NAMESPACE); + assertContainsString(message, XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG); throw e; } } @@ -264,9 +442,9 @@ public class NetconfMappingTest extends AbstractConfigTest { edit("netconfMessages/namespaces/editConfig_differentNamespaceTO.xml"); } catch (NetconfDocumentedException e) { String message = e.getMessage(); - assertThat(message, JUnitMatchers.containsString("Unrecognised elements")); - assertThat(message, JUnitMatchers.containsString("simple-int2")); - assertThat(message, JUnitMatchers.containsString("dto_d")); + assertContainsString(message, "Unrecognised elements"); + assertContainsString(message, "simple-int2"); + assertContainsString(message, "dto_d"); throw e; } } @@ -277,13 +455,9 @@ public class NetconfMappingTest extends AbstractConfigTest { edit("netconfMessages/namespaces/editConfig_sameAttrDifferentNamespacesList.xml"); } catch (NetconfDocumentedException e) { String message = e.getMessage(); - assertThat(message, - JUnitMatchers.containsString("Element binaryLeaf present multiple times with different namespaces")); - assertThat(message, - JUnitMatchers.containsString("urn:opendaylight:params:xml:ns:yang:controller:test:impl")); - assertThat(message, - JUnitMatchers - .containsString(XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG)); + assertContainsString(message, "Element binaryLeaf present multiple times with different namespaces"); + assertContainsString(message, TEST_NAMESPACE); + assertContainsString(message, XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG); throw e; } } @@ -295,7 +469,7 @@ public class NetconfMappingTest extends AbstractConfigTest { edit("netconfMessages/namespaces/editConfig_typeNameConfigAttributeMatching.xml"); commit(); - Element response = getConfigRunning(); + Document response = getConfigRunning(); checkTypeConfigAttribute(response); } @@ -320,8 +494,8 @@ public class NetconfMappingTest extends AbstractConfigTest { try { edit(file); } catch (NetconfDocumentedException e) { - assertThat(e.getMessage(), JUnitMatchers.containsString("Unrecognised elements")); - assertThat(e.getMessage(), JUnitMatchers.containsString("unknownAttribute")); + assertContainsString(e.getMessage(), "Unrecognised elements"); + assertContainsString(e.getMessage(), "unknownAttribute"); continue; } fail("Unrecognised test should throw exception " + file); @@ -337,7 +511,7 @@ public class NetconfMappingTest extends AbstractConfigTest { edit("netconfMessages/editConfig.xml"); commit(); - Element response = getConfigRunning(); + Document response = getConfigRunning(); final int allInstances = response.getElementsByTagName("instance").getLength(); edit("netconfMessages/editConfig_replace_module.xml"); @@ -366,267 +540,163 @@ public class NetconfMappingTest extends AbstractConfigTest { executeOp(discardOp, "netconfMessages/discardChanges.xml"); } - private void checkBinaryLeafEdited(final Element response) { - final NodeList children = response.getElementsByTagName("binaryLeaf"); - assertEquals(3, children.getLength()); - final StringBuffer buf = new StringBuffer(); - for (int i = 0; i < 3; i++) { - final Element e = (Element) children.item(i); - buf.append(XmlElement.fromDomElement(e).getTextContent()); - } - assertEquals("810", buf.toString()); - + private void checkBinaryLeafEdited(final Document response) throws NodeTestException, SAXException, IOException { + assertContainsElement(response, readXmlToElement("YmluYXJ5")); + assertContainsElement(response, readXmlToElement("ZGVmYXVsdEJpbg==")); } - private void checkTypeConfigAttribute(Element response) { + private void checkTypedefs(final Document response) throws NodeTestException, SAXException, IOException { - XmlElement modulesElement = XmlElement.fromDomElement(response).getOnlyChildElement("data") - .getOnlyChildElement("modules"); + assertContainsElement(response, readXmlToElement("10")); + // Default + assertContainsElement(response, readXmlToElement("1")); - XmlElement configAttributeType = null; - for (XmlElement moduleElement : modulesElement.getChildElements("module")) { - for (XmlElement type : moduleElement.getChildElements("type")) { - if (type.getAttribute(XmlUtil.XMLNS_ATTRIBUTE_KEY).equals("") == false) { - configAttributeType = type; - } - } - } + assertContainsElement(response, readXmlToElement("20")); + // Default + assertContainsElement(response, readXmlToElement("2")); - assertEquals("configAttributeType", configAttributeType.getTextContent()); + assertContainsElement(response, readXmlToElement("TWO")); + // Default + assertContainsElement(response, readXmlToElement("ONE")); } - private Map> getMbes() throws Exception { - final List yangDependencies = getYangs(); - - final Map> mBeanEntries = Maps.newHashMap(); - mBeanEntries.putAll(new MbeParser().parseYangFiles(yangDependencies).getModuleMXBeanEntryMap()); - - return mBeanEntries; + private void assertContainsString(String string, String substring) { + assertThat(string, JUnitMatchers.containsString(substring)); } - @Test - public void testConfigNetconfRuntime() throws Exception { - - ModuleIdentifier id = new ModuleIdentifier(NetconfTestImplModuleFactory.NAME, "instance"); - RootRuntimeBeanRegistrator rootReg = new RootRuntimeBeanRegistratorImpl(internalJmxRegistrator, id); - NetconfTestImplRuntimeRegistrator registrator = new NetconfTestImplRuntimeRegistrator(rootReg); - - NetconfTestImplRuntimeRegistration a = registerRoot(registrator); - InnerRunningDataRuntimeRegistration reg = registerInner(a); - registerInner2(reg); - - id = new ModuleIdentifier(NetconfTestImplModuleFactory.NAME, "instance2"); - rootReg = new RootRuntimeBeanRegistratorImpl(internalJmxRegistrator, id); - registrator = new NetconfTestImplRuntimeRegistrator(rootReg); - - a = registerRoot(registrator); - registerAdditional(a); - registerAdditional(a); - registerAdditional(a); - registerAdditional(a); - reg = registerInner(a); - registerInner2(reg); - reg = registerInner(a); - registerInner2(reg); - registerInner2(reg); - reg = registerInner(a); - registerInner2(reg); - registerInner2(reg); - registerInner2(reg); - reg = registerInner(a); - registerInner2(reg); - registerInner2(reg); - registerInner2(reg); - registerInner2(reg); - - Element response = get(); - - System.err.println(XmlUtil.toString(response)); - - assertEquals(2, getElementsSize(response, "module")); - assertEquals(2, getElementsSize(response, "asdf")); - assertEquals(5, getElementsSize(response, "inner-running-data")); - assertEquals(5, getElementsSize(response, "deep2")); - assertEquals(11, getElementsSize(response, "inner-inner-running-data")); - assertEquals(11, getElementsSize(response, "deep3")); - assertEquals(11 * 2, getElementsSize(response, "list-of-strings")); - assertEquals(4, getElementsSize(response, "inner-running-data-additional")); - assertEquals(4, getElementsSize(response, "deep4")); - // TODO assert keys - - RuntimeRpc netconf = new RuntimeRpc(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID); - - response = executeOp(netconf, "netconfMessages/rpc.xml"); - assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("testarg1".toUpperCase())); + private void checkEnum(final Document response) throws NetconfDocumentedException { + XmlElement modulesElement = XmlElement.fromDomElement(response.getDocumentElement()).getOnlyChildElement("data") + .getOnlyChildElement("modules"); - response = executeOp(netconf, "netconfMessages/rpcInner.xml"); - assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("ok")); + String enumName = "extended-enum"; + String enumContent = "TWO"; - response = executeOp(netconf, "netconfMessages/rpcInnerInner.xml"); - assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("true")); + for (XmlElement moduleElement : modulesElement.getChildElements("module")) { + String name = moduleElement.getOnlyChildElement("name").getTextContent(); + if(name.equals(INSTANCE_NAME)) { + XmlElement enumAttr = moduleElement.getOnlyChildElement(enumName); + assertEquals(enumContent, enumAttr.getTextContent()); + return; + } + } - response = executeOp(netconf, "netconfMessages/rpcInnerInner_complex_output.xml"); - assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("1")); - assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("2")); + fail("Enum attribute " + enumName + ":" + enumContent + " not present in " + XmlUtil.toString(response)); } - private Element get() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException { - Get getOp = new Get(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID); - return executeOp(getOp, "netconfMessages/get.xml"); + private void checkTestingDeps(Document response) { + int testingDepsSize = response.getElementsByTagName("testing-deps").getLength(); + assertEquals(2, testingDepsSize); } - private int getElementsSize(Element response, String elementName) { - return response.getElementsByTagName(elementName).getLength(); - } - - private Object registerAdditional(final NetconfTestImplRuntimeRegistration a) { - class InnerRunningDataAdditionalRuntimeMXBeanTest implements InnerRunningDataAdditionalRuntimeMXBean { - - private final int simpleInt; - private final String simpleString; - - public InnerRunningDataAdditionalRuntimeMXBeanTest(final int simpleInt, final String simpleString) { - this.simpleInt = simpleInt; - this.simpleString = simpleString; - } - - @Override - public Integer getSimpleInt3() { - return this.simpleInt; - } + private void checkTypeConfigAttribute(Document response) throws NetconfDocumentedException { - @Override - public Deep4 getDeep4() { - final Deep4 d = new Deep4(); - d.setBoool(false); - return d; - } + XmlElement modulesElement = XmlElement.fromDomElement(response.getDocumentElement()).getOnlyChildElement("data") + .getOnlyChildElement("modules"); - @Override - public String getSimpleString() { - return this.simpleString; - } + List expectedValues = Lists.newArrayList("default-string", "configAttributeType"); + Set configAttributeType = Sets.newHashSet(); - @Override - public void noArgInner() { + for (XmlElement moduleElement : modulesElement.getChildElements("module")) { + for (XmlElement type : moduleElement.getChildElements("type")) { + if (type.getNamespaceOptionally().isPresent()) { + configAttributeType.add(type.getTextContent()); + } } - } - final int simpleInt = counter++; - return a.register(new InnerRunningDataAdditionalRuntimeMXBeanTest(simpleInt, "randomString_" + simpleInt)); + for (String expectedValue : expectedValues) { + assertTrue(configAttributeType.contains(expectedValue)); + } } - private void registerInner2(final InnerRunningDataRuntimeRegistration reg) { - class InnerInnerRunningDataRuntimeMXBeanTest implements InnerInnerRunningDataRuntimeMXBean { - - private final int simpleInt; - - public InnerInnerRunningDataRuntimeMXBeanTest(final int simpleInt) { - this.simpleInt = simpleInt; - } - - @Override - public List getNotStateBean() { - final NotStateBean notStateBean = new NotStateBean(); - final NotStateBeanInternal notStateBeanInternal = new NotStateBeanInternal(); - notStateBean.setNotStateBeanInternal(Lists.newArrayList(notStateBeanInternal)); - return Lists.newArrayList(notStateBean); - } - - @Override - public Integer getSimpleInt3() { - return this.simpleInt; - } - - @Override - public Deep3 getDeep3() { - return new Deep3(); - } - - @Override - public List getListOfStrings() { - return Lists.newArrayList("l1", "l2"); - } + private Map> getMbes() throws Exception { + final List yangDependencies = getYangs(); - @Override - public List listOutput() { - return Lists.newArrayList(new RetValList()); - } + final Map> mBeanEntries = Maps.newHashMap(); + YangParserImpl yangParser = new YangParserImpl(); + final SchemaContext schemaContext = yangParser.resolveSchemaContext(new HashSet<>(yangParser.parseYangModelsFromStreamsMapped(yangDependencies).values())); + YangStoreServiceImpl yangStoreService = new YangStoreServiceImpl(new SchemaContextProvider() { @Override - public Boolean noArgInnerInner(Integer integer, Boolean aBoolean) { - return aBoolean; + public SchemaContext getSchemaContext() { + return schemaContext ; } + }); + mBeanEntries.putAll(yangStoreService.getYangStoreSnapshot().getModuleMXBeanEntryMap()); - @Override - public RetValContainer containerOutput() { - return new RetValContainer(); - } + return mBeanEntries; + } - @Override - public List leafListOutput() { - return Lists.newArrayList("1", "2"); - } + private Set getModules() throws Exception { + SchemaContext resolveSchemaContext = getSchemaContext(); + return resolveSchemaContext.getModules(); + } - } + private SchemaContext getSchemaContext() throws Exception { + final List yangDependencies = getYangs(); + YangParserImpl parser = new YangParserImpl(); - reg.register(new InnerInnerRunningDataRuntimeMXBeanTest(counter++)); + Set allYangModules = parser.parseYangModelsFromStreams(yangDependencies); + return parser.resolveSchemaContext(Sets + .newHashSet(allYangModules)); } - private static int counter = 1000; - - private InnerRunningDataRuntimeRegistration registerInner(final NetconfTestImplRuntimeRegistration a) { + @Test + public void testConfigNetconfRuntime() throws Exception { - class InnerRunningDataRuntimeMXBeanTest implements InnerRunningDataRuntimeMXBean { + createModule(INSTANCE_NAME); - private final int simpleInt; + edit("netconfMessages/editConfig.xml"); + checkBinaryLeafEdited(getConfigCandidate()); - public InnerRunningDataRuntimeMXBeanTest(final int simpleInt) { - this.simpleInt = simpleInt; - } + // check after edit + commit(); + Document response = get(); - @Override - public Integer getSimpleInt3() { - return this.simpleInt; - } + assertEquals(2/*With runtime beans*/ + 2 /*Without runtime beans*/, getElementsSize(response, "module")); + // data from state + assertEquals(2, getElementsSize(response, "asdf")); + // data from running config + assertEquals(2, getElementsSize(response, "simple-short")); + + assertEquals(8, getElementsSize(response, "inner-running-data")); + assertEquals(8, getElementsSize(response, "deep2")); + assertEquals(8 * 4, getElementsSize(response, "inner-inner-running-data")); + assertEquals(8 * 4, getElementsSize(response, "deep3")); + assertEquals(8 * 4 * 2, getElementsSize(response, "list-of-strings")); + assertEquals(8, getElementsSize(response, "inner-running-data-additional")); + assertEquals(8, getElementsSize(response, "deep4")); + // TODO assert keys - @Override - public Deep2 getDeep2() { - return new Deep2(); - } + RuntimeRpc netconf = new RuntimeRpc(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID); - } - return a.register(new InnerRunningDataRuntimeMXBeanTest(counter++)); - } + response = executeOp(netconf, "netconfMessages/rpc.xml"); + assertContainsElementWithText(response, "testarg1"); - private NetconfTestImplRuntimeRegistration registerRoot(final NetconfTestImplRuntimeRegistrator registrator) { - final NetconfTestImplRuntimeRegistration a = registrator.register(new NetconfTestImplRuntimeMXBean() { + response = executeOp(netconf, "netconfMessages/rpcInner.xml"); + Document expectedReplyOk = XmlFileLoader.xmlFileToDocument("netconfMessages/rpc-reply_ok.xml"); + XMLUnit.setIgnoreWhitespace(true); + XMLAssert.assertXMLEqual(expectedReplyOk, response); - @Override - public Long getCreatedSessions() { - return 11L; - } + response = executeOp(netconf, "netconfMessages/rpcInnerInner.xml"); + assertContainsElementWithText(response, "true"); - @Override - public Asdf getAsdf() { - final Asdf asdf = new Asdf(); - asdf.setSimpleInt(55); - asdf.setSimpleString("asdf"); - return asdf; - } + response = executeOp(netconf, "netconfMessages/rpcInnerInner_complex_output.xml"); + assertContainsElementWithText(response, "1"); + assertContainsElementWithText(response, "2"); + } - @Override - public String noArg(final String arg1) { - return arg1.toUpperCase(); - } + private Document get() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException { + Get getOp = new Get(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID); + return executeOp(getOp, "netconfMessages/get.xml"); + } - }); - return a; + private int getElementsSize(Document response, String elementName) { + return response.getElementsByTagName(elementName).getLength(); } - private Element executeOp(final NetconfOperation op, final String filename) throws ParserConfigurationException, + private Document executeOp(final NetconfOperation op, final String filename) throws ParserConfigurationException, SAXException, IOException, NetconfDocumentedException { final Document request = XmlFileLoader.xmlFileToDocument(filename); @@ -636,14 +706,14 @@ public class NetconfMappingTest extends AbstractConfigTest { Preconditions.checkState(priority != HandlingPriority.CANNOT_HANDLE); - final Document response = op.handle(request, netconfOperationRouter); + final Document response = op.handle(request, NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT); logger.debug("Got response\n{}", XmlUtil.toString(response)); - return response.getDocumentElement(); + return response; } private List getYangs() throws FileNotFoundException { List paths = Arrays.asList("/META-INF/yang/config.yang", "/META-INF/yang/rpc-context.yang", - "/META-INF/yang/config-test.yang", "/META-INF/yang/config-test-impl.yang", + "/META-INF/yang/config-test.yang", "/META-INF/yang/config-test-impl.yang", "/META-INF/yang/test-types.yang", "/META-INF/yang/ietf-inet-types.yang"); final Collection yangDependencies = new ArrayList<>(); for (String path : paths) { @@ -654,8 +724,8 @@ public class NetconfMappingTest extends AbstractConfigTest { return Lists.newArrayList(yangDependencies); } - private void setModule(final NetconfTestImplModuleMXBean mxBean, final ConfigTransactionJMXClient transaction) - throws InstanceAlreadyExistsException { + private void setModule(final NetconfTestImplModuleMXBean mxBean, final ConfigTransactionJMXClient transaction, String depName) + throws InstanceAlreadyExistsException, InstanceNotFoundException { mxBean.setSimpleInt((long) 44); mxBean.setBinaryLeaf(new byte[] { 8, 7, 9 }); final DtoD dtob = getDtoD(); @@ -685,7 +755,15 @@ public class NetconfMappingTest extends AbstractConfigTest { mxBean.setComplexList(Lists. newArrayList()); mxBean.setSimpleList(Lists. newArrayList()); - final ObjectName testingDepOn = transaction.createModule(this.factory2.getImplementationName(), "dep"); + final ObjectName testingDepOn = transaction.createModule(this.factory2.getImplementationName(), depName); + int i = 1; + for (Class sInterface : factory2.getImplementedServiceIntefaces()) { + ServiceInterfaceAnnotation annotation = sInterface.getAnnotation(ServiceInterfaceAnnotation.class); + transaction.saveServiceReference( + transaction.getServiceInterfaceName(annotation.namespace(), annotation.localName()), "ref_from_code_to_" + depName + "_" + i++, + testingDepOn); + + } mxBean.setTestingDep(testingDepOn); }