/*
* Copyright (c) 2017 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.yangtools.yang.stmt;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Date;
import org.junit.Test;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
import org.opendaylight.yangtools.yang.parser.spi.meta.InvalidSubstatementException;
import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
public class DeviationResolutionTest {
@Test
public void testDeviateNotSupported() throws Exception {
final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
"/deviation-resolution-test/deviation-not-supported");
assertNotNull(schemaContext);
final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
final Module rootModule = schemaContext.findModuleByName("root", revision);
assertNotNull(rootModule);
final ContainerSchemaNode myContA = (ContainerSchemaNode) rootModule.getDataChildByName(
QName.create(rootModule.getQNameModule(), "my-cont-a"));
assertNotNull(myContA);
assertEquals(1, myContA.getChildNodes().size());
assertNotNull(myContA.getDataChildByName(QName.create(rootModule.getQNameModule(), "my-leaf-a3")));
final ContainerSchemaNode myContB = (ContainerSchemaNode) rootModule.getDataChildByName(
QName.create(rootModule.getQNameModule(), "my-cont-b"));
assertNull(myContB);
final Module importedModule = schemaContext.findModuleByName("imported", revision);
assertNotNull(importedModule);
final ContainerSchemaNode myContC = (ContainerSchemaNode) importedModule.getDataChildByName(
QName.create(importedModule.getQNameModule(), "my-cont-c"));
assertNotNull(myContC);
assertEquals(2, myContC.getChildNodes().size());
assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c1")));
assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c2")));
}
@Test
public void testDeviateAdd() throws Exception {
final SchemaContext schemaContext = StmtTestUtils.parseYangSource(
"/deviation-resolution-test/deviation-add/foo.yang");
assertNotNull(schemaContext);
final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
final Module fooModule = schemaContext.findModuleByName("foo", revision);
assertNotNull(fooModule);
final LeafListSchemaNode myLeafList = (LeafListSchemaNode) fooModule.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-leaf-list"));
assertNotNull(myLeafList);
assertFalse(myLeafList.isConfiguration());
assertEquals(3, myLeafList.getDefaults().size());
assertEquals(10, myLeafList.getConstraints().getMaxElements().intValue());
assertEquals(5, myLeafList.getConstraints().getMinElements().intValue());
assertNotNull(myLeafList.getType().getUnits());
final ListSchemaNode myList = (ListSchemaNode) fooModule.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-list"));
assertNotNull(myList);
assertEquals(2, myList.getUniqueConstraints().size());
final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) fooModule.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-choice"));
assertNotNull(myChoice);
assertEquals("c2", myChoice.getDefaultCase());
final RpcDefinition myRpc = fooModule.getRpcs().iterator().next();
final ContainerSchemaNode input = myRpc.getInput();
assertEquals(2, input.getConstraints().getMustConstraints().size());
final ContainerSchemaNode output = myRpc.getOutput();
assertEquals(2, output.getConstraints().getMustConstraints().size());
final NotificationDefinition myNotification = fooModule.getNotifications().iterator().next();
assertEquals(2, myNotification.getConstraints().getMustConstraints().size());
final AnyXmlSchemaNode myAnyxml = (AnyXmlSchemaNode) fooModule.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-anyxml"));
assertNotNull(myAnyxml);
assertTrue(myAnyxml.getConstraints().isMandatory());
assertEquals(2, myAnyxml.getUnknownSchemaNodes().size());
}
@Test
public void testDeviateReplace() throws Exception {
final SchemaContext schemaContext = StmtTestUtils.parseYangSource(
"/deviation-resolution-test/deviation-replace/foo.yang");
assertNotNull(schemaContext);
final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
final Module fooModule = schemaContext.findModuleByName("foo", revision);
assertNotNull(fooModule);
final LeafSchemaNode myLeaf = (LeafSchemaNode) fooModule.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-leaf"));
assertNotNull(myLeaf);
assertTrue(myLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
assertNotNull(myLeaf.getUnits());
assertEquals("bytes", myLeaf.getUnits());
assertNotNull(myLeaf.getDefault());
assertEquals("10", myLeaf.getDefault());
final LeafListSchemaNode myLeafList = (LeafListSchemaNode) fooModule.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-leaf-list-test"));
assertNotNull(myLeafList);
assertEquals(6, myLeafList.getConstraints().getMaxElements().intValue());
assertEquals(3, myLeafList.getConstraints().getMinElements().intValue());
assertTrue(myLeafList.isConfiguration());
final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) fooModule.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-choice"));
assertNotNull(myChoice);
assertFalse(myChoice.getConstraints().isMandatory());
assertEquals(1, myChoice.getUnknownSchemaNodes().size());
assertEquals("new arg", myChoice.getUnknownSchemaNodes().iterator().next().getNodeParameter());
final ContainerSchemaNode myCont = (ContainerSchemaNode) fooModule.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-cont"));
assertNotNull(myCont);
final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-aug-leaf"));
assertNotNull(myAugLeaf);
assertTrue(myAugLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
assertNotNull(myAugLeaf.getUnits());
assertEquals("seconds", myAugLeaf.getUnits());
assertNotNull(myAugLeaf.getDefault());
assertEquals("new-def-val", myAugLeaf.getDefault());
assertEquals(1, myAugLeaf.getUnknownSchemaNodes().size());
assertEquals("new arg", myAugLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-used-leaf"));
assertNotNull(myUsedLeaf);
assertTrue(myUsedLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
assertNotNull(myUsedLeaf.getUnits());
assertEquals("weeks", myUsedLeaf.getUnits());
assertNotNull(myUsedLeaf.getDefault());
assertEquals("new-def-val", myUsedLeaf.getDefault());
assertEquals(1, myUsedLeaf.getUnknownSchemaNodes().size());
assertEquals("new arg", myUsedLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
}
@Test
public void testDeviateDelete() throws Exception {
final SchemaContext schemaContext = StmtTestUtils.parseYangSource(
"/deviation-resolution-test/deviation-delete/foo.yang");
assertNotNull(schemaContext);
final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
final Module fooModule = schemaContext.findModuleByName("foo", revision);
assertNotNull(fooModule);
final LeafSchemaNode myLeaf = (LeafSchemaNode) fooModule.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-leaf"));
assertNotNull(myLeaf);
assertNull(myLeaf.getDefault());
assertNull(myLeaf.getUnits());
assertEquals(0, myLeaf.getUnknownSchemaNodes().size());
final LeafListSchemaNode myLeafList = (LeafListSchemaNode) fooModule.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-leaf-list"));
assertNotNull(myLeafList);
assertEquals(0, myLeafList.getDefaults().size());
assertEquals(0, myLeafList.getConstraints().getMustConstraints().size());
final ListSchemaNode myList = (ListSchemaNode) fooModule.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-list"));
assertNotNull(myList);
assertEquals(0, myList.getUniqueConstraints().size());
assertEquals(0, myList.getUnknownSchemaNodes().size());
final ContainerSchemaNode myCont = (ContainerSchemaNode) fooModule.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-cont"));
assertNotNull(myCont);
final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-aug-leaf"));
assertNotNull(myAugLeaf);
assertNull(myAugLeaf.getDefault());
assertNull(myAugLeaf.getUnits());
assertEquals(0, myAugLeaf.getConstraints().getMustConstraints().size());
assertEquals(0, myAugLeaf.getUnknownSchemaNodes().size());
final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
QName.create(fooModule.getQNameModule(), "my-used-leaf"));
assertNotNull(myUsedLeaf);
assertNull(myUsedLeaf.getDefault());
assertNull(myUsedLeaf.getUnits());
assertEquals(0, myUsedLeaf.getConstraints().getMustConstraints().size());
assertEquals(0, myUsedLeaf.getUnknownSchemaNodes().size());
}
@Test
public void shouldFailOnInvalidYang10Model() throws Exception {
try {
StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo10-invalid.yang");
fail("An exception should have been thrown.");
} catch (final ReactorException ex) {
final Throwable cause = ex.getCause();
assertTrue(cause instanceof InvalidSubstatementException);
assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
}
}
@Test
public void shouldFailOnInvalidYang10Model2() throws Exception {
try {
StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-delete/foo10-invalid.yang");
fail("An exception should have been thrown.");
} catch (final ReactorException ex) {
final Throwable cause = ex.getCause();
assertTrue(cause instanceof InvalidSubstatementException);
assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
}
}
@Test
public void shouldFailOnInvalidDeviationTarget() throws Exception {
try {
StmtTestUtils.parseYangSource("/deviation-resolution-test/foo-invalid-deviation-target.yang");
fail("An exception should have been thrown.");
} catch (final ReactorException ex) {
final Throwable cause = ex.getCause();
assertTrue(cause instanceof InferenceException);
assertTrue(cause.getMessage().startsWith("(foo?revision=2017-01-20)my-cont is not a valid deviation " +
"target for substatement (urn:ietf:params:xml:ns:yang:yin:1)max-elements."));
}
}
@Test
public void shouldFailOnInvalidDeviationPath() throws Exception {
try {
StmtTestUtils.parseYangSource("/deviation-resolution-test/foo-invalid-deviation-path.yang");
fail("An exception should have been thrown.");
} catch (final ReactorException ex) {
final Throwable cause = ex.getCause().getCause();
assertTrue(cause instanceof InferenceException);
assertTrue(cause.getMessage().startsWith("Deviation target 'Absolute{path=[(foo?revision=2017-01-20)invalid, " +
"(foo?revision=2017-01-20)path]}' not found"));
}
}
@Test
public void shouldFailOnInvalidDeviateAdd() throws Exception {
try {
StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-invalid.yang");
fail("An exception should have been thrown.");
} catch (final ReactorException ex) {
final Throwable cause = ex.getCause();
assertTrue(cause instanceof InferenceException);
assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
":yin:1)config to target node (foo?revision=2017-01-20)my-leaf because it is already defined in" +
" target and can appear only once."));
}
}
@Test
public void shouldFailOnInvalidDeviateAdd2() throws Exception {
try {
StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-invalid-2.yang");
fail("An exception should have been thrown.");
} catch (final ReactorException ex) {
final Throwable cause = ex.getCause();
assertTrue(cause instanceof InferenceException);
assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
":yin:1)default to target node (foo?revision=2017-01-20)my-leaf because it is already defined in" +
" target and can appear only once."));
}
}
@Test
public void shouldFailOnInvalidDeviateAdd3() throws Exception {
try {
StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-invalid-4.yang");
fail("An exception should have been thrown.");
} catch (final ReactorException ex) {
final Throwable cause = ex.getCause();
assertTrue(cause instanceof InferenceException);
assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
":yin:1)default to target node (foo?revision=2017-02-01)my-used-leaf because it is already " +
"defined in target and can appear only once."));
}
}
@Test
public void shouldFailOnInvalidDeviateReplace() throws Exception {
try {
StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-replace/foo-invalid.yang");
fail("An exception should have been thrown.");
} catch (final ReactorException ex) {
final Throwable cause = ex.getCause();
assertTrue(cause instanceof InferenceException);
assertTrue(cause.getMessage().startsWith("Deviation cannot replace substatement " +
"(urn:ietf:params:xml:ns:yang:yin:1)units in target node (foo?revision=2017-01-20)my-leaf " +
"because it does not exist in target node."));
}
}
@Test
public void shouldLogInvalidDeviateReplaceAttempt() throws Exception {
final PrintStream stdout = System.out;
final ByteArrayOutputStream output = new ByteArrayOutputStream();
final String testLog;
System.setOut(new PrintStream(output, true, "UTF-8"));
StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-replace/foo-invalid-2.yang");
testLog = output.toString();
assertTrue(testLog.contains("Deviation cannot replace substatement (urn:ietf:params:xml:ns:yang:yin:1)default" +
" in target leaf-list (foo?revision=2017-01-20)my-leaf-list because a leaf-list can have multiple " +
"default statements."));
System.setOut(stdout);
}
@Test
public void shouldLogInvalidDeviateDeleteAttempt() throws Exception {
final PrintStream stdout = System.out;
final ByteArrayOutputStream output = new ByteArrayOutputStream();
final String testLog;
System.setOut(new PrintStream(output, true, "UTF-8"));
StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-delete/foo-invalid.yang");
testLog = output.toString();
assertTrue(testLog.contains("Deviation cannot delete substatement (urn:ietf:params:xml:ns:yang:yin:1)units " +
"with argument 'seconds' in target node (foo?revision=2017-01-20)my-leaf because it does not exist " +
"in the target node."));
System.setOut(stdout);
}
@Test
public void shouldFailOnInvalidDeviateAddSubstatement() throws Exception {
try {
StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-invalid-3.yang");
fail("An exception should have been thrown.");
} catch (final ReactorException ex) {
final Throwable cause = ex.getCause();
assertTrue(cause instanceof InvalidSubstatementException);
assertTrue(cause.getMessage().startsWith("TYPE is not valid for DEVIATE."));
}
}
@Test
public void shouldFailOnInvalidDeviateReplaceSubstatement() throws Exception {
try {
StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-replace/foo-invalid-3.yang");
fail("An exception should have been thrown.");
} catch (final ReactorException ex) {
final Throwable cause = ex.getCause();
assertTrue(cause instanceof InvalidSubstatementException);
assertTrue(cause.getMessage().startsWith("MUST is not valid for DEVIATE."));
}
}
@Test
public void shouldFailOnInvalidDeviateDeleteSubstatement() throws Exception {
try {
StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-delete/foo-invalid-2.yang");
fail("An exception should have been thrown.");
} catch (final ReactorException ex) {
final Throwable cause = ex.getCause();
assertTrue(cause instanceof InvalidSubstatementException);
assertTrue(cause.getMessage().startsWith("CONFIG is not valid for DEVIATE."));
}
}
}