Committed by
Gerrit Code Review
config ang key validation and UT for the same
Change-Id: I507740fc9da3f3da5fb3c88a7414f87db6251c5b
Showing
42 changed files
with
899 additions
and
63 deletions
| ... | @@ -99,7 +99,7 @@ public class YangContainer extends YangNode implements YangLeavesHolder, YangCom | ... | @@ -99,7 +99,7 @@ public class YangContainer extends YangNode implements YangLeavesHolder, YangCom |
| 99 | /** | 99 | /** |
| 100 | * If container maintains config data. | 100 | * If container maintains config data. |
| 101 | */ | 101 | */ |
| 102 | - private boolean isConfig; | 102 | + private Boolean isConfig; |
| 103 | 103 | ||
| 104 | /** | 104 | /** |
| 105 | * Description of container. | 105 | * Description of container. |
| ... | @@ -174,7 +174,7 @@ public class YangContainer extends YangNode implements YangLeavesHolder, YangCom | ... | @@ -174,7 +174,7 @@ public class YangContainer extends YangNode implements YangLeavesHolder, YangCom |
| 174 | * | 174 | * |
| 175 | * @return the isConfig | 175 | * @return the isConfig |
| 176 | */ | 176 | */ |
| 177 | - public boolean isConfig() { | 177 | + public Boolean isConfig() { |
| 178 | return isConfig; | 178 | return isConfig; |
| 179 | } | 179 | } |
| 180 | 180 | ||
| ... | @@ -378,7 +378,70 @@ public class YangContainer extends YangNode implements YangLeavesHolder, YangCom | ... | @@ -378,7 +378,70 @@ public class YangContainer extends YangNode implements YangLeavesHolder, YangCom |
| 378 | */ | 378 | */ |
| 379 | @Override | 379 | @Override |
| 380 | public void validateDataOnExit() throws DataModelException { | 380 | public void validateDataOnExit() throws DataModelException { |
| 381 | - // TODO auto-generated method stub, to be implemented by parser | 381 | + List<YangLeaf> leaves = getListOfLeaf(); |
| 382 | + List<YangLeafList> leafLists = getListOfLeafList(); | ||
| 383 | + | ||
| 384 | + setDefaultConfigValueToChild(leaves, leafLists); | ||
| 385 | + validateConfig(leaves, leafLists); | ||
| 386 | + } | ||
| 387 | + | ||
| 388 | + /** | ||
| 389 | + * Sets the config's value to all leaf if leaf's config statement is not specified. | ||
| 390 | + * | ||
| 391 | + * @param leaves list of leaf attributes of container. | ||
| 392 | + * @param leafLists list of leaf-list attributes of container. | ||
| 393 | + */ | ||
| 394 | + private void setDefaultConfigValueToChild(List<YangLeaf> leaves, List<YangLeafList> leafLists) { | ||
| 395 | + | ||
| 396 | + /* If "config" is not specified, the default is the same as the parent | ||
| 397 | + schema node's "config" value.*/ | ||
| 398 | + if (leaves != null) { | ||
| 399 | + for (YangLeaf leaf : leaves) { | ||
| 400 | + if (leaf.isConfig() == null) { | ||
| 401 | + leaf.setConfig(isConfig); | ||
| 402 | + } | ||
| 403 | + } | ||
| 404 | + } | ||
| 405 | + | ||
| 406 | + /* If "config" is not specified, the default is the same as the parent | ||
| 407 | + schema node's "config" value.*/ | ||
| 408 | + if (leafLists != null) { | ||
| 409 | + for (YangLeafList leafList : leafLists) { | ||
| 410 | + if (leafList.isConfig() == null) { | ||
| 411 | + leafList.setConfig(isConfig); | ||
| 412 | + } | ||
| 413 | + } | ||
| 414 | + } | ||
| 415 | + } | ||
| 416 | + | ||
| 417 | + /** | ||
| 418 | + * Validates config statement of container. | ||
| 419 | + * | ||
| 420 | + * @param leaves list of leaf attributes of container. | ||
| 421 | + * @param leafLists list of leaf-list attributes of container. | ||
| 422 | + * @throws DataModelException a violation of data model rules. | ||
| 423 | + */ | ||
| 424 | + private void validateConfig(List<YangLeaf> leaves, List<YangLeafList> leafLists) throws DataModelException { | ||
| 425 | + | ||
| 426 | + /* If a node has "config" set to "false", no node underneath it can have | ||
| 427 | + "config" set to "true".*/ | ||
| 428 | + if ((!isConfig) && (leaves != null)) { | ||
| 429 | + for (YangLeaf leaf : leaves) { | ||
| 430 | + if (leaf.isConfig()) { | ||
| 431 | + throw new DataModelException("If a container has \"config\" set to \"false\", no node underneath " + | ||
| 432 | + "it can have \"config\" set to \"true\"."); | ||
| 433 | + } | ||
| 434 | + } | ||
| 435 | + } | ||
| 436 | + | ||
| 437 | + if ((!isConfig) && (leafLists != null)) { | ||
| 438 | + for (YangLeafList leafList : leafLists) { | ||
| 439 | + if (leafList.isConfig()) { | ||
| 440 | + throw new DataModelException("If a container has \"config\" set to \"false\", no node underneath " + | ||
| 441 | + "it can have \"config\" set to \"true\"."); | ||
| 442 | + } | ||
| 443 | + } | ||
| 444 | + } | ||
| 382 | } | 445 | } |
| 383 | 446 | ||
| 384 | /** | 447 | /** | ... | ... |
| ... | @@ -67,7 +67,7 @@ public class YangLeaf implements YangCommonInfo, Parsable { | ... | @@ -67,7 +67,7 @@ public class YangLeaf implements YangCommonInfo, Parsable { |
| 67 | /** | 67 | /** |
| 68 | * If the leaf is a config parameter. | 68 | * If the leaf is a config parameter. |
| 69 | */ | 69 | */ |
| 70 | - private boolean isConfig; | 70 | + private Boolean isConfig; |
| 71 | 71 | ||
| 72 | /** | 72 | /** |
| 73 | * description of leaf. | 73 | * description of leaf. |
| ... | @@ -128,7 +128,7 @@ public class YangLeaf implements YangCommonInfo, Parsable { | ... | @@ -128,7 +128,7 @@ public class YangLeaf implements YangCommonInfo, Parsable { |
| 128 | * | 128 | * |
| 129 | * @return if config flag. | 129 | * @return if config flag. |
| 130 | */ | 130 | */ |
| 131 | - public boolean isConfig() { | 131 | + public Boolean isConfig() { |
| 132 | return isConfig; | 132 | return isConfig; |
| 133 | } | 133 | } |
| 134 | 134 | ... | ... |
| ... | @@ -62,7 +62,7 @@ public class YangLeafList implements YangCommonInfo, Parsable { | ... | @@ -62,7 +62,7 @@ public class YangLeafList implements YangCommonInfo, Parsable { |
| 62 | /** | 62 | /** |
| 63 | * If the leaf-list is a config parameter. | 63 | * If the leaf-list is a config parameter. |
| 64 | */ | 64 | */ |
| 65 | - private boolean isConfig; | 65 | + private Boolean isConfig; |
| 66 | 66 | ||
| 67 | /** | 67 | /** |
| 68 | * Description of leaf-list. | 68 | * Description of leaf-list. |
| ... | @@ -150,7 +150,7 @@ public class YangLeafList implements YangCommonInfo, Parsable { | ... | @@ -150,7 +150,7 @@ public class YangLeafList implements YangCommonInfo, Parsable { |
| 150 | * | 150 | * |
| 151 | * @return the config flag. | 151 | * @return the config flag. |
| 152 | */ | 152 | */ |
| 153 | - public boolean isConfig() { | 153 | + public Boolean isConfig() { |
| 154 | return isConfig; | 154 | return isConfig; |
| 155 | } | 155 | } |
| 156 | 156 | ... | ... |
| ... | @@ -77,7 +77,7 @@ public class YangList extends YangNode | ... | @@ -77,7 +77,7 @@ public class YangList extends YangNode |
| 77 | /** | 77 | /** |
| 78 | * If list maintains config data. | 78 | * If list maintains config data. |
| 79 | */ | 79 | */ |
| 80 | - private boolean isConfig; | 80 | + private Boolean isConfig; |
| 81 | 81 | ||
| 82 | /** | 82 | /** |
| 83 | * Description of list. | 83 | * Description of list. |
| ... | @@ -199,7 +199,7 @@ public class YangList extends YangNode | ... | @@ -199,7 +199,7 @@ public class YangList extends YangNode |
| 199 | * | 199 | * |
| 200 | * @return the isConfig | 200 | * @return the isConfig |
| 201 | */ | 201 | */ |
| 202 | - public boolean isConfig() { | 202 | + public Boolean isConfig() { |
| 203 | return isConfig; | 203 | return isConfig; |
| 204 | } | 204 | } |
| 205 | 205 | ||
| ... | @@ -254,11 +254,18 @@ public class YangList extends YangNode | ... | @@ -254,11 +254,18 @@ public class YangList extends YangNode |
| 254 | * Add a key field name. | 254 | * Add a key field name. |
| 255 | * | 255 | * |
| 256 | * @param key key field name. | 256 | * @param key key field name. |
| 257 | + * @throws DataModelException a violation of data model rules. | ||
| 257 | */ | 258 | */ |
| 258 | - public void addKey(String key) { | 259 | + public void addKey(String key) throws DataModelException { |
| 259 | if (getKeyList() == null) { | 260 | if (getKeyList() == null) { |
| 260 | setKeyList(new LinkedList<String>()); | 261 | setKeyList(new LinkedList<String>()); |
| 261 | } | 262 | } |
| 263 | + | ||
| 264 | + if (getKeyList().contains(key)) { | ||
| 265 | + throw new DataModelException("A leaf identifier must not appear more than once in the\n" + | ||
| 266 | + " key"); | ||
| 267 | + } | ||
| 268 | + | ||
| 262 | getKeyList().add(key); | 269 | getKeyList().add(key); |
| 263 | } | 270 | } |
| 264 | 271 | ||
| ... | @@ -431,7 +438,167 @@ public class YangList extends YangNode | ... | @@ -431,7 +438,167 @@ public class YangList extends YangNode |
| 431 | */ | 438 | */ |
| 432 | @Override | 439 | @Override |
| 433 | public void validateDataOnExit() throws DataModelException { | 440 | public void validateDataOnExit() throws DataModelException { |
| 434 | - // TODO auto-generated method stub, to be implemented by parser | 441 | + List<String> keyList = getKeyList(); |
| 442 | + List<YangLeaf> leaves = getListOfLeaf(); | ||
| 443 | + List<YangLeafList> leafLists = getListOfLeafList(); | ||
| 444 | + | ||
| 445 | + setDefaultConfigValueToChild(leaves, leafLists); | ||
| 446 | + validateConfig(leaves, leafLists); | ||
| 447 | + | ||
| 448 | + /* A list must have atleast one key leaf if config is true */ | ||
| 449 | + if ((isConfig) | ||
| 450 | + && ((keyList == null) || (leaves == null && leafLists == null))) { | ||
| 451 | + throw new DataModelException("A list must have atleast one key leaf if config is true;"); | ||
| 452 | + } else if (keyList != null) { | ||
| 453 | + if (leaves != null) { | ||
| 454 | + validateLeafKey(leaves, keyList); | ||
| 455 | + } | ||
| 456 | + | ||
| 457 | + if (leafLists != null) { | ||
| 458 | + validateLeafListKey(leafLists, keyList); | ||
| 459 | + } | ||
| 460 | + } | ||
| 461 | + } | ||
| 462 | + | ||
| 463 | + /** | ||
| 464 | + * Sets the config's value to all leaf if leaf's config statement is not specified. | ||
| 465 | + * | ||
| 466 | + * @param leaves list of leaf attributes of YANG list. | ||
| 467 | + * @param leafLists list of leaf-list attributes of YANG list. | ||
| 468 | + */ | ||
| 469 | + private void setDefaultConfigValueToChild(List<YangLeaf> leaves, List<YangLeafList> leafLists) { | ||
| 470 | + | ||
| 471 | + /* If "config" is not specified, the default is the same as the parent | ||
| 472 | + schema node's "config" value.*/ | ||
| 473 | + if (leaves != null) { | ||
| 474 | + for (YangLeaf leaf : leaves) { | ||
| 475 | + if (leaf.isConfig() == null) { | ||
| 476 | + leaf.setConfig(isConfig); | ||
| 477 | + } | ||
| 478 | + } | ||
| 479 | + } | ||
| 480 | + | ||
| 481 | + /* If "config" is not specified, the default is the same as the parent | ||
| 482 | + schema node's "config" value.*/ | ||
| 483 | + if (leafLists != null) { | ||
| 484 | + for (YangLeafList leafList : leafLists) { | ||
| 485 | + if (leafList.isConfig() == null) { | ||
| 486 | + leafList.setConfig(isConfig); | ||
| 487 | + } | ||
| 488 | + } | ||
| 489 | + } | ||
| 490 | + } | ||
| 491 | + | ||
| 492 | + /** | ||
| 493 | + * Validates config statement of YANG list. | ||
| 494 | + * | ||
| 495 | + * @param leaves list of leaf attributes of YANG list. | ||
| 496 | + * @param leafLists list of leaf-list attributes of YANG list. | ||
| 497 | + * @throws DataModelException a violation of data model rules. | ||
| 498 | + */ | ||
| 499 | + private void validateConfig(List<YangLeaf> leaves, List<YangLeafList> leafLists) throws DataModelException { | ||
| 500 | + | ||
| 501 | + /* If a node has "config" set to "false", no node underneath it can have | ||
| 502 | + "config" set to "true".*/ | ||
| 503 | + if ((!isConfig) && (leaves != null)) { | ||
| 504 | + for (YangLeaf leaf : leaves) { | ||
| 505 | + if (leaf.isConfig()) { | ||
| 506 | + throw new DataModelException("If a list has \"config\" set to \"false\", no node underneath " + | ||
| 507 | + "it can have \"config\" set to \"true\"."); | ||
| 508 | + } | ||
| 509 | + } | ||
| 510 | + } | ||
| 511 | + | ||
| 512 | + if ((!isConfig) && (leafLists != null)) { | ||
| 513 | + for (YangLeafList leafList : leafLists) { | ||
| 514 | + if (leafList.isConfig()) { | ||
| 515 | + throw new DataModelException("If a list has \"config\" set to \"false\", no node underneath " + | ||
| 516 | + "it can have \"config\" set to \"true\"."); | ||
| 517 | + } | ||
| 518 | + } | ||
| 519 | + } | ||
| 520 | + } | ||
| 521 | + | ||
| 522 | + /** | ||
| 523 | + * Validates key statement of list. | ||
| 524 | + * | ||
| 525 | + * @param leaves list of leaf attributes of list. | ||
| 526 | + * @param keyList list of key attributes of list. | ||
| 527 | + * @throws DataModelException a violation of data model rules. | ||
| 528 | + */ | ||
| 529 | + private void validateLeafKey(List<YangLeaf> leaves, List<String> keyList) throws DataModelException { | ||
| 530 | + boolean leafFound = false; | ||
| 531 | + List<YangLeaf> keyLeaves = new LinkedList<>(); | ||
| 532 | + | ||
| 533 | + /* 1. Leaf identifier must refer to a child leaf of the list | ||
| 534 | + 2. A leaf that is part of the key must not be the built-in type "empty". */ | ||
| 535 | + for (String key : keyList) { | ||
| 536 | + for (YangLeaf leaf : leaves) { | ||
| 537 | + if (key.equals(leaf.getLeafName())) { | ||
| 538 | + if (leaf.getDataType().getDataTypeName().replace("\"", "").equals("empty")) { | ||
| 539 | + throw new DataModelException(" A leaf that is part of the key must not be the built-in " + | ||
| 540 | + "type \"empty\"."); | ||
| 541 | + } | ||
| 542 | + leafFound = true; | ||
| 543 | + keyLeaves.add(leaf); | ||
| 544 | + break; | ||
| 545 | + } | ||
| 546 | + } | ||
| 547 | + if (!leafFound) { | ||
| 548 | + throw new DataModelException("Leaf identifier must refer to a child leaf of the list"); | ||
| 549 | + } | ||
| 550 | + leafFound = false; | ||
| 551 | + } | ||
| 552 | + | ||
| 553 | + /* All key leafs in a list MUST have the same value for their "config" | ||
| 554 | + as the list itself. */ | ||
| 555 | + for (YangLeaf keyLeaf : keyLeaves) { | ||
| 556 | + if (isConfig != keyLeaf.isConfig()) { | ||
| 557 | + throw new DataModelException("All key leafs in a list must have the same value for their" + | ||
| 558 | + " \"config\" as the list itself."); | ||
| 559 | + } | ||
| 560 | + } | ||
| 561 | + } | ||
| 562 | + | ||
| 563 | + /** | ||
| 564 | + * Validates key statement of list. | ||
| 565 | + * | ||
| 566 | + * @param leafLists list of leaf-list attributes of list. | ||
| 567 | + * @param keyList list of key attributes of list. | ||
| 568 | + * @throws DataModelException a violation of data model rules. | ||
| 569 | + */ | ||
| 570 | + private void validateLeafListKey(List<YangLeafList> leafLists, List<String> keyList) throws DataModelException { | ||
| 571 | + boolean leafFound = false; | ||
| 572 | + List<YangLeafList> keyLeafLists = new LinkedList<>(); | ||
| 573 | + | ||
| 574 | + /* 1. Leaf identifier must refer to a child leaf of the list | ||
| 575 | + 2. A leaf that is part of the key must not be the built-in type "empty". */ | ||
| 576 | + for (String key : keyList) { | ||
| 577 | + for (YangLeafList leafList : leafLists) { | ||
| 578 | + if (key.equals(leafList.getLeafName())) { | ||
| 579 | + if (leafList.getDataType().getDataTypeName().replace("\"", "").equals("empty")) { | ||
| 580 | + throw new DataModelException(" A leaf-list that is part of the key must not be the built-in " + | ||
| 581 | + "type \"empty\"."); | ||
| 582 | + } | ||
| 583 | + leafFound = true; | ||
| 584 | + keyLeafLists.add(leafList); | ||
| 585 | + break; | ||
| 586 | + } | ||
| 587 | + } | ||
| 588 | + if (!leafFound) { | ||
| 589 | + throw new DataModelException("Leaf-list identifier must refer to a child leaf of the list"); | ||
| 590 | + } | ||
| 591 | + leafFound = false; | ||
| 592 | + } | ||
| 593 | + | ||
| 594 | + /* All key leafs in a list MUST have the same value for their "config" | ||
| 595 | + as the list itself. */ | ||
| 596 | + for (YangLeafList keyLeafList : keyLeafLists) { | ||
| 597 | + if (isConfig() != keyLeafList.isConfig()) { | ||
| 598 | + throw new DataModelException("All key leaf-lists in a list must have the same value for their" + | ||
| 599 | + " \"config\" as the list itself."); | ||
| 600 | + } | ||
| 601 | + } | ||
| 435 | } | 602 | } |
| 436 | 603 | ||
| 437 | /* (non-Javadoc) | 604 | /* (non-Javadoc) | ... | ... |
utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/ContainerListener.java
| ... | @@ -27,6 +27,7 @@ import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser; | ... | @@ -27,6 +27,7 @@ import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser; |
| 27 | import org.onosproject.yangutils.parser.exceptions.ParserException; | 27 | import org.onosproject.yangutils.parser.exceptions.ParserException; |
| 28 | import org.onosproject.yangutils.parser.impl.TreeWalkListener; | 28 | import org.onosproject.yangutils.parser.impl.TreeWalkListener; |
| 29 | import org.onosproject.yangutils.parser.impl.YangUtilsParserManager; | 29 | import org.onosproject.yangutils.parser.impl.YangUtilsParserManager; |
| 30 | +import org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation; | ||
| 30 | 31 | ||
| 31 | import static org.onosproject.yangutils.parser.ParsableDataType.CONTAINER_DATA; | 32 | import static org.onosproject.yangutils.parser.ParsableDataType.CONTAINER_DATA; |
| 32 | import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY; | 33 | import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY; |
| ... | @@ -94,6 +95,7 @@ public final class ContainerListener { | ... | @@ -94,6 +95,7 @@ public final class ContainerListener { |
| 94 | public static void processContainerEntry(TreeWalkListener listener, | 95 | public static void processContainerEntry(TreeWalkListener listener, |
| 95 | GeneratedYangParser.ContainerStatementContext ctx) { | 96 | GeneratedYangParser.ContainerStatementContext ctx) { |
| 96 | 97 | ||
| 98 | + YangNode parentNode; | ||
| 97 | // Check for stack to be non empty. | 99 | // Check for stack to be non empty. |
| 98 | checkStackIsNotEmpty(listener, MISSING_HOLDER, CONTAINER_DATA, ctx.IDENTIFIER().getText(), ENTRY); | 100 | checkStackIsNotEmpty(listener, MISSING_HOLDER, CONTAINER_DATA, ctx.IDENTIFIER().getText(), ENTRY); |
| 99 | 101 | ||
| ... | @@ -105,8 +107,14 @@ public final class ContainerListener { | ... | @@ -105,8 +107,14 @@ public final class ContainerListener { |
| 105 | YangContainer container = new YangContainer(); | 107 | YangContainer container = new YangContainer(); |
| 106 | container.setName(ctx.IDENTIFIER().getText()); | 108 | container.setName(ctx.IDENTIFIER().getText()); |
| 107 | 109 | ||
| 108 | - Parsable curData = listener.getParsedDataStack().peek(); | 110 | + /* If "config" is not specified, the default is the same as the parent |
| 111 | + schema node's "config" value. */ | ||
| 112 | + if (ctx.configStatement().isEmpty()) { | ||
| 113 | + boolean parentConfig = ListenerValidation.getParentNodeConfig(listener); | ||
| 114 | + container.setConfig(parentConfig); | ||
| 115 | + } | ||
| 109 | 116 | ||
| 117 | + Parsable curData = listener.getParsedDataStack().peek(); | ||
| 110 | if ((curData instanceof YangModule) || (curData instanceof YangContainer) | 118 | if ((curData instanceof YangModule) || (curData instanceof YangContainer) |
| 111 | || (curData instanceof YangList)) { | 119 | || (curData instanceof YangList)) { |
| 112 | YangNode curNode = (YangNode) curData; | 120 | YangNode curNode = (YangNode) curData; |
| ... | @@ -137,6 +145,13 @@ public final class ContainerListener { | ... | @@ -137,6 +145,13 @@ public final class ContainerListener { |
| 137 | checkStackIsNotEmpty(listener, MISSING_HOLDER, CONTAINER_DATA, ctx.IDENTIFIER().getText(), EXIT); | 145 | checkStackIsNotEmpty(listener, MISSING_HOLDER, CONTAINER_DATA, ctx.IDENTIFIER().getText(), EXIT); |
| 138 | 146 | ||
| 139 | if (listener.getParsedDataStack().peek() instanceof YangContainer) { | 147 | if (listener.getParsedDataStack().peek() instanceof YangContainer) { |
| 148 | + YangContainer yangContainer = (YangContainer) listener.getParsedDataStack().peek(); | ||
| 149 | + try { | ||
| 150 | + yangContainer.validateDataOnExit(); | ||
| 151 | + } catch (DataModelException e) { | ||
| 152 | + throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA, | ||
| 153 | + CONTAINER_DATA, ctx.IDENTIFIER().getText(), EXIT, e.getMessage())); | ||
| 154 | + } | ||
| 140 | listener.getParsedDataStack().pop(); | 155 | listener.getParsedDataStack().pop(); |
| 141 | } else { | 156 | } else { |
| 142 | throw new ParserException(constructListenerErrorMessage(MISSING_CURRENT_HOLDER, CONTAINER_DATA, | 157 | throw new ParserException(constructListenerErrorMessage(MISSING_CURRENT_HOLDER, CONTAINER_DATA, | ... | ... |
| ... | @@ -17,15 +17,20 @@ | ... | @@ -17,15 +17,20 @@ |
| 17 | package org.onosproject.yangutils.parser.impl.listeners; | 17 | package org.onosproject.yangutils.parser.impl.listeners; |
| 18 | 18 | ||
| 19 | import org.onosproject.yangutils.datamodel.YangList; | 19 | import org.onosproject.yangutils.datamodel.YangList; |
| 20 | +import org.onosproject.yangutils.datamodel.exceptions.DataModelException; | ||
| 20 | import org.onosproject.yangutils.parser.Parsable; | 21 | import org.onosproject.yangutils.parser.Parsable; |
| 21 | -import org.onosproject.yangutils.parser.ParsableDataType; | ||
| 22 | import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser; | 22 | import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser; |
| 23 | import org.onosproject.yangutils.parser.exceptions.ParserException; | 23 | import org.onosproject.yangutils.parser.exceptions.ParserException; |
| 24 | import org.onosproject.yangutils.parser.impl.TreeWalkListener; | 24 | import org.onosproject.yangutils.parser.impl.TreeWalkListener; |
| 25 | -import org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation; | 25 | + |
| 26 | -import org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction; | 26 | +import static org.onosproject.yangutils.parser.ParsableDataType.KEY_DATA; |
| 27 | -import org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType; | 27 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY; |
| 28 | -import org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation; | 28 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage; |
| 29 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructExtendedListenerErrorMessage; | ||
| 30 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER; | ||
| 31 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA; | ||
| 32 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER; | ||
| 33 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty; | ||
| 29 | 34 | ||
| 30 | /* | 35 | /* |
| 31 | * Reference: RFC6020 and YANG ANTLR Grammar | 36 | * Reference: RFC6020 and YANG ANTLR Grammar |
| ... | @@ -61,9 +66,7 @@ public final class KeyListener { | ... | @@ -61,9 +66,7 @@ public final class KeyListener { |
| 61 | GeneratedYangParser.KeyStatementContext ctx) { | 66 | GeneratedYangParser.KeyStatementContext ctx) { |
| 62 | 67 | ||
| 63 | // Check for stack to be non empty. | 68 | // Check for stack to be non empty. |
| 64 | - ListenerValidation.checkStackIsNotEmpty(listener, ListenerErrorType.MISSING_HOLDER, | 69 | + checkStackIsNotEmpty(listener, MISSING_HOLDER, KEY_DATA, ctx.string().getText(), ENTRY); |
| 65 | - ParsableDataType.KEY_DATA, String.valueOf(ctx.string().getText()), | ||
| 66 | - ListenerErrorLocation.ENTRY); | ||
| 67 | 70 | ||
| 68 | Parsable tmpData = listener.getParsedDataStack().peek(); | 71 | Parsable tmpData = listener.getParsedDataStack().peek(); |
| 69 | if (listener.getParsedDataStack().peek() instanceof YangList) { | 72 | if (listener.getParsedDataStack().peek() instanceof YangList) { |
| ... | @@ -72,17 +75,24 @@ public final class KeyListener { | ... | @@ -72,17 +75,24 @@ public final class KeyListener { |
| 72 | if (tmpKeyValue.contains(" ")) { | 75 | if (tmpKeyValue.contains(" ")) { |
| 73 | String[] keyValues = tmpKeyValue.split(" "); | 76 | String[] keyValues = tmpKeyValue.split(" "); |
| 74 | for (String keyValue : keyValues) { | 77 | for (String keyValue : keyValues) { |
| 78 | + try { | ||
| 75 | yangList.addKey(keyValue); | 79 | yangList.addKey(keyValue); |
| 80 | + } catch (DataModelException e) { | ||
| 81 | + throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA, KEY_DATA, | ||
| 82 | + ctx.string().getText(), ENTRY, e.getMessage())); | ||
| 83 | + } | ||
| 76 | } | 84 | } |
| 77 | } else { | 85 | } else { |
| 86 | + try { | ||
| 78 | yangList.addKey(tmpKeyValue); | 87 | yangList.addKey(tmpKeyValue); |
| 88 | + } catch (DataModelException e) { | ||
| 89 | + throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA, KEY_DATA, | ||
| 90 | + ctx.string().getText(), ENTRY, e.getMessage())); | ||
| 91 | + } | ||
| 79 | } | 92 | } |
| 80 | } else { | 93 | } else { |
| 81 | - throw new ParserException(ListenerErrorMessageConstruction | 94 | + throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, KEY_DATA, ctx.string().getText(), |
| 82 | - .constructListenerErrorMessage(ListenerErrorType.INVALID_HOLDER, | 95 | + ENTRY)); |
| 83 | - ParsableDataType.KEY_DATA, | ||
| 84 | - String.valueOf(ctx.string().getText()), | ||
| 85 | - ListenerErrorLocation.ENTRY)); | ||
| 86 | } | 96 | } |
| 87 | } | 97 | } |
| 88 | } | 98 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -17,6 +17,8 @@ | ... | @@ -17,6 +17,8 @@ |
| 17 | package org.onosproject.yangutils.parser.impl.listeners; | 17 | package org.onosproject.yangutils.parser.impl.listeners; |
| 18 | 18 | ||
| 19 | import org.onosproject.yangutils.datamodel.YangList; | 19 | import org.onosproject.yangutils.datamodel.YangList; |
| 20 | +import org.onosproject.yangutils.datamodel.YangContainer; | ||
| 21 | +import org.onosproject.yangutils.datamodel.YangModule; | ||
| 20 | import org.onosproject.yangutils.datamodel.YangNode; | 22 | import org.onosproject.yangutils.datamodel.YangNode; |
| 21 | import org.onosproject.yangutils.datamodel.YangNodeType; | 23 | import org.onosproject.yangutils.datamodel.YangNodeType; |
| 22 | import org.onosproject.yangutils.datamodel.exceptions.DataModelException; | 24 | import org.onosproject.yangutils.datamodel.exceptions.DataModelException; |
| ... | @@ -26,11 +28,20 @@ import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser; | ... | @@ -26,11 +28,20 @@ import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser; |
| 26 | import org.onosproject.yangutils.parser.exceptions.ParserException; | 28 | import org.onosproject.yangutils.parser.exceptions.ParserException; |
| 27 | import org.onosproject.yangutils.parser.impl.TreeWalkListener; | 29 | import org.onosproject.yangutils.parser.impl.TreeWalkListener; |
| 28 | import org.onosproject.yangutils.parser.impl.YangUtilsParserManager; | 30 | import org.onosproject.yangutils.parser.impl.YangUtilsParserManager; |
| 29 | -import org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation; | ||
| 30 | -import org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction; | ||
| 31 | -import org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType; | ||
| 32 | import org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation; | 31 | import org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation; |
| 33 | 32 | ||
| 33 | +import static org.onosproject.yangutils.parser.ParsableDataType.LIST_DATA; | ||
| 34 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY; | ||
| 35 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.EXIT; | ||
| 36 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructExtendedListenerErrorMessage; | ||
| 37 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage; | ||
| 38 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_CURRENT_HOLDER; | ||
| 39 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER; | ||
| 40 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER; | ||
| 41 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA; | ||
| 42 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_CARDINALITY; | ||
| 43 | +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty; | ||
| 44 | + | ||
| 34 | /* | 45 | /* |
| 35 | * Reference: RFC6020 and YANG ANTLR Grammar | 46 | * Reference: RFC6020 and YANG ANTLR Grammar |
| 36 | * | 47 | * |
| ... | @@ -89,40 +100,37 @@ public final class ListListener { | ... | @@ -89,40 +100,37 @@ public final class ListListener { |
| 89 | 100 | ||
| 90 | YangNode curNode; | 101 | YangNode curNode; |
| 91 | 102 | ||
| 92 | - ListenerValidation.checkStackIsNotEmpty(listener, ListenerErrorType.MISSING_HOLDER, | 103 | + checkStackIsNotEmpty(listener, MISSING_HOLDER, LIST_DATA, ctx.IDENTIFIER().getText(), ENTRY); |
| 93 | - ParsableDataType.LIST_DATA, String.valueOf(ctx.IDENTIFIER().getText()), | ||
| 94 | - ListenerErrorLocation.ENTRY); | ||
| 95 | 104 | ||
| 96 | boolean result = validateSubStatementsCardinality(ctx); | 105 | boolean result = validateSubStatementsCardinality(ctx); |
| 97 | if (!result) { | 106 | if (!result) { |
| 98 | - throw new ParserException(ListenerErrorMessageConstruction | 107 | + throw new ParserException(constructListenerErrorMessage(INVALID_CARDINALITY, yangConstruct, "", ENTRY)); |
| 99 | - .constructListenerErrorMessage(ListenerErrorType.INVALID_CARDINALITY, | ||
| 100 | - yangConstruct, "", ListenerErrorLocation.ENTRY)); | ||
| 101 | } | 108 | } |
| 102 | 109 | ||
| 103 | YangList yangList = new YangList(YangNodeType.LIST_NODE); | 110 | YangList yangList = new YangList(YangNodeType.LIST_NODE); |
| 104 | yangList.setName(ctx.IDENTIFIER().getText()); | 111 | yangList.setName(ctx.IDENTIFIER().getText()); |
| 105 | 112 | ||
| 113 | + /* If "config" is not specified, the default is the same as the parent | ||
| 114 | + schema node's "config" value. */ | ||
| 115 | + if (ctx.configStatement().isEmpty()) { | ||
| 116 | + boolean parentConfig = ListenerValidation.getParentNodeConfig(listener); | ||
| 117 | + yangList.setConfig(parentConfig); | ||
| 118 | + } | ||
| 119 | + | ||
| 106 | Parsable curData = listener.getParsedDataStack().peek(); | 120 | Parsable curData = listener.getParsedDataStack().peek(); |
| 107 | - if (curData instanceof YangNode) { | 121 | + if ((curData instanceof YangModule) || (curData instanceof YangContainer) |
| 122 | + || (curData instanceof YangList)) { | ||
| 108 | curNode = (YangNode) curData; | 123 | curNode = (YangNode) curData; |
| 109 | try { | 124 | try { |
| 110 | curNode.addChild(yangList); | 125 | curNode.addChild(yangList); |
| 111 | } catch (DataModelException e) { | 126 | } catch (DataModelException e) { |
| 112 | - throw new ParserException(ListenerErrorMessageConstruction | 127 | + throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA, |
| 113 | - .constructExtendedListenerErrorMessage(ListenerErrorType.UNHANDLED_PARSED_DATA, | 128 | + LIST_DATA, ctx.IDENTIFIER().getText(), ENTRY, e.getMessage())); |
| 114 | - ParsableDataType.LIST_DATA, | ||
| 115 | - String.valueOf(ctx.IDENTIFIER().getText()), | ||
| 116 | - ListenerErrorLocation.ENTRY, | ||
| 117 | - e.getMessage())); | ||
| 118 | } | 129 | } |
| 119 | listener.getParsedDataStack().push(yangList); | 130 | listener.getParsedDataStack().push(yangList); |
| 120 | } else { | 131 | } else { |
| 121 | - throw new ParserException(ListenerErrorMessageConstruction | 132 | + throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, LIST_DATA, |
| 122 | - .constructListenerErrorMessage(ListenerErrorType.INVALID_HOLDER, | 133 | + ctx.IDENTIFIER().getText(), ENTRY)); |
| 123 | - ParsableDataType.LIST_DATA, | ||
| 124 | - String.valueOf(ctx.IDENTIFIER().getText()), | ||
| 125 | - ListenerErrorLocation.ENTRY)); | ||
| 126 | } | 134 | } |
| 127 | } | 135 | } |
| 128 | 136 | ||
| ... | @@ -136,18 +144,20 @@ public final class ListListener { | ... | @@ -136,18 +144,20 @@ public final class ListListener { |
| 136 | public static void processListExit(TreeWalkListener listener, | 144 | public static void processListExit(TreeWalkListener listener, |
| 137 | GeneratedYangParser.ListStatementContext ctx) { | 145 | GeneratedYangParser.ListStatementContext ctx) { |
| 138 | 146 | ||
| 139 | - ListenerValidation.checkStackIsNotEmpty(listener, ListenerErrorType.MISSING_HOLDER, | 147 | + checkStackIsNotEmpty(listener, MISSING_HOLDER, LIST_DATA, ctx.IDENTIFIER().getText(), EXIT); |
| 140 | - ParsableDataType.LIST_DATA, String.valueOf(ctx.IDENTIFIER().getText()), | ||
| 141 | - ListenerErrorLocation.EXIT); | ||
| 142 | 148 | ||
| 143 | if (listener.getParsedDataStack().peek() instanceof YangList) { | 149 | if (listener.getParsedDataStack().peek() instanceof YangList) { |
| 150 | + YangList yangList = (YangList) listener.getParsedDataStack().peek(); | ||
| 151 | + try { | ||
| 152 | + yangList.validateDataOnExit(); | ||
| 153 | + } catch (DataModelException e) { | ||
| 154 | + throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA, | ||
| 155 | + LIST_DATA, ctx.IDENTIFIER().getText(), EXIT, e.getMessage())); | ||
| 156 | + } | ||
| 144 | listener.getParsedDataStack().pop(); | 157 | listener.getParsedDataStack().pop(); |
| 145 | } else { | 158 | } else { |
| 146 | - throw new ParserException(ListenerErrorMessageConstruction | 159 | + throw new ParserException(constructListenerErrorMessage(MISSING_CURRENT_HOLDER, LIST_DATA, |
| 147 | - .constructListenerErrorMessage(ListenerErrorType.INVALID_HOLDER, | 160 | + ctx.IDENTIFIER().getText(), EXIT)); |
| 148 | - ParsableDataType.LIST_DATA, | ||
| 149 | - String.valueOf(ctx.IDENTIFIER().getText()), | ||
| 150 | - ListenerErrorLocation.EXIT)); | ||
| 151 | } | 161 | } |
| 152 | } | 162 | } |
| 153 | 163 | ||
| ... | @@ -157,7 +167,7 @@ public final class ListListener { | ... | @@ -157,7 +167,7 @@ public final class ListListener { |
| 157 | * @param ctx context object of the grammar rule. | 167 | * @param ctx context object of the grammar rule. |
| 158 | * @return true/false validation success or failure. | 168 | * @return true/false validation success or failure. |
| 159 | */ | 169 | */ |
| 160 | - public static boolean validateSubStatementsCardinality(GeneratedYangParser.ListStatementContext ctx) { | 170 | + private static boolean validateSubStatementsCardinality(GeneratedYangParser.ListStatementContext ctx) { |
| 161 | 171 | ||
| 162 | if ((!ctx.keyStatement().isEmpty()) | 172 | if ((!ctx.keyStatement().isEmpty()) |
| 163 | && (ctx.keyStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) { | 173 | && (ctx.keyStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) { | ... | ... |
| ... | @@ -16,6 +16,10 @@ | ... | @@ -16,6 +16,10 @@ |
| 16 | 16 | ||
| 17 | package org.onosproject.yangutils.parser.impl.parserutils; | 17 | package org.onosproject.yangutils.parser.impl.parserutils; |
| 18 | 18 | ||
| 19 | +import org.onosproject.yangutils.datamodel.YangContainer; | ||
| 20 | +import org.onosproject.yangutils.datamodel.YangList; | ||
| 21 | +import org.onosproject.yangutils.datamodel.YangNode; | ||
| 22 | +import org.onosproject.yangutils.parser.Parsable; | ||
| 19 | import org.onosproject.yangutils.parser.ParsableDataType; | 23 | import org.onosproject.yangutils.parser.ParsableDataType; |
| 20 | import org.onosproject.yangutils.parser.exceptions.ParserException; | 24 | import org.onosproject.yangutils.parser.exceptions.ParserException; |
| 21 | import org.onosproject.yangutils.parser.impl.TreeWalkListener; | 25 | import org.onosproject.yangutils.parser.impl.TreeWalkListener; |
| ... | @@ -83,4 +87,25 @@ public final class ListenerValidation { | ... | @@ -83,4 +87,25 @@ public final class ListenerValidation { |
| 83 | throw new ParserException(message); | 87 | throw new ParserException(message); |
| 84 | } | 88 | } |
| 85 | } | 89 | } |
| 90 | + | ||
| 91 | + /** | ||
| 92 | + * Returns parent node config value, if top node does not specify a config statement | ||
| 93 | + * then default value true is returned. | ||
| 94 | + * | ||
| 95 | + * @param listener listener's object. | ||
| 96 | + * @return true/false parent's config value. | ||
| 97 | + */ | ||
| 98 | + public static boolean getParentNodeConfig(TreeWalkListener listener) { | ||
| 99 | + YangNode parentNode; | ||
| 100 | + Parsable curData = listener.getParsedDataStack().peek(); | ||
| 101 | + if (curData instanceof YangNode) { | ||
| 102 | + parentNode = ((YangNode) curData).getParent(); | ||
| 103 | + if (parentNode instanceof YangContainer) { | ||
| 104 | + return ((YangContainer) parentNode).isConfig(); | ||
| 105 | + } else if (parentNode instanceof YangList) { | ||
| 106 | + return ((YangList) parentNode).isConfig(); | ||
| 107 | + } | ||
| 108 | + } | ||
| 109 | + return true; | ||
| 110 | + } | ||
| 86 | } | 111 | } | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -104,4 +104,141 @@ public class KeyListenerTest { | ... | @@ -104,4 +104,141 @@ public class KeyListenerTest { |
| 104 | thrown.expectMessage("mismatched input 'leaf' expecting {';', '+'}"); | 104 | thrown.expectMessage("mismatched input 'leaf' expecting {';', '+'}"); |
| 105 | YangNode node = manager.getDataModel("src/test/resources/KeyWithoutStatementEnd.yang"); | 105 | YangNode node = manager.getDataModel("src/test/resources/KeyWithoutStatementEnd.yang"); |
| 106 | } | 106 | } |
| 107 | + | ||
| 108 | + /** | ||
| 109 | + * Checks key values are set correctly. | ||
| 110 | + */ | ||
| 111 | + @Test | ||
| 112 | + public void processConfigFalseNoKey() throws IOException, ParserException { | ||
| 113 | + YangNode node = manager.getDataModel("src/test/resources/ConfigFalseNoKey.yang"); | ||
| 114 | + | ||
| 115 | + assertThat((node instanceof YangModule), is(true)); | ||
| 116 | + assertThat(node.getNodeType(), is(YangNodeType.MODULE_NODE)); | ||
| 117 | + YangModule yangNode = (YangModule) node; | ||
| 118 | + assertThat(yangNode.getName(), is("Test")); | ||
| 119 | + | ||
| 120 | + // Check whether the list is child of module | ||
| 121 | + YangList yangList = (YangList) yangNode.getChild(); | ||
| 122 | + assertThat(yangList.getName(), is("valid")); | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + /** | ||
| 126 | + * Checks key values are set correctly. | ||
| 127 | + */ | ||
| 128 | + @Test | ||
| 129 | + public void processConfigFalseValidKeyValidLeaf() throws IOException, ParserException { | ||
| 130 | + YangNode node = manager.getDataModel("src/test/resources/ConfigFalseValidKeyValidLeaf.yang"); | ||
| 131 | + | ||
| 132 | + assertThat((node instanceof YangModule), is(true)); | ||
| 133 | + assertThat(node.getNodeType(), is(YangNodeType.MODULE_NODE)); | ||
| 134 | + YangModule yangNode = (YangModule) node; | ||
| 135 | + assertThat(yangNode.getName(), is("Test")); | ||
| 136 | + | ||
| 137 | + // Check whether the list is child of module | ||
| 138 | + YangList yangList = (YangList) yangNode.getChild(); | ||
| 139 | + assertThat(yangList.getName(), is("valid")); | ||
| 140 | + | ||
| 141 | + ListIterator<String> keyList = yangList.getKeyList().listIterator(); | ||
| 142 | + assertThat(keyList.next(), is("invalid-interval")); | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + /** | ||
| 146 | + * Checks key values are set correctly. | ||
| 147 | + */ | ||
| 148 | + @Test | ||
| 149 | + public void processConfigFalseValidKeyValidLeafList() throws IOException, ParserException { | ||
| 150 | + YangNode node = manager.getDataModel("src/test/resources/ConfigFalseValidKeyValidLeafList.yang"); | ||
| 151 | + | ||
| 152 | + assertThat((node instanceof YangModule), is(true)); | ||
| 153 | + assertThat(node.getNodeType(), is(YangNodeType.MODULE_NODE)); | ||
| 154 | + YangModule yangNode = (YangModule) node; | ||
| 155 | + assertThat(yangNode.getName(), is("Test")); | ||
| 156 | + | ||
| 157 | + // Check whether the list is child of module | ||
| 158 | + YangList yangList = (YangList) yangNode.getChild(); | ||
| 159 | + assertThat(yangList.getName(), is("valid")); | ||
| 160 | + | ||
| 161 | + ListIterator<String> keyList = yangList.getKeyList().listIterator(); | ||
| 162 | + assertThat(keyList.next(), is("invalid-interval")); | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + /** | ||
| 166 | + * Checks whether exception is thrown when list's config is set to true and there is no key. | ||
| 167 | + */ | ||
| 168 | + @Test | ||
| 169 | + public void processConfigTrueNoKey() throws IOException, ParserException { | ||
| 170 | + thrown.expect(ParserException.class); | ||
| 171 | + thrown.expectMessage("A list must have atleast one key leaf if config is true"); | ||
| 172 | + YangNode node = manager.getDataModel("src/test/resources/ConfigTrueNoKey.yang"); | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + /** | ||
| 176 | + * Checks whether exception is thrown when list's config is set to true and there is no leaf. | ||
| 177 | + */ | ||
| 178 | + @Test | ||
| 179 | + public void processConfigTrueNoleafNoLeafList() throws IOException, ParserException { | ||
| 180 | + thrown.expect(ParserException.class); | ||
| 181 | + thrown.expectMessage("A list must have atleast one key leaf if config is true"); | ||
| 182 | + YangNode node = manager.getDataModel("src/test/resources/ConfigTrueNoleafNoLeafList.yang"); | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + /** | ||
| 186 | + * Checks key values are set correctly. | ||
| 187 | + */ | ||
| 188 | + @Test | ||
| 189 | + public void processConfigTrueValidKeyValidLeaf() throws IOException, ParserException { | ||
| 190 | + YangNode node = manager.getDataModel("src/test/resources/ConfigTrueValidKeyValidLeaf.yang"); | ||
| 191 | + | ||
| 192 | + assertThat((node instanceof YangModule), is(true)); | ||
| 193 | + assertThat(node.getNodeType(), is(YangNodeType.MODULE_NODE)); | ||
| 194 | + YangModule yangNode = (YangModule) node; | ||
| 195 | + assertThat(yangNode.getName(), is("Test")); | ||
| 196 | + | ||
| 197 | + // Check whether the list is child of module | ||
| 198 | + YangList yangList = (YangList) yangNode.getChild(); | ||
| 199 | + assertThat(yangList.getName(), is("valid")); | ||
| 200 | + | ||
| 201 | + ListIterator<String> keyList = yangList.getKeyList().listIterator(); | ||
| 202 | + assertThat(keyList.next(), is("invalid-interval")); | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + /** | ||
| 206 | + * Checks whether exception is thrown when key leaf identifier is not found in list. | ||
| 207 | + */ | ||
| 208 | + @Test | ||
| 209 | + public void processInvalidLeafIdentifier() throws IOException, ParserException { | ||
| 210 | + thrown.expect(ParserException.class); | ||
| 211 | + thrown.expectMessage("Leaf identifier must refer to a child leaf of the list"); | ||
| 212 | + YangNode node = manager.getDataModel("src/test/resources/InvalidLeafIdentifier.yang"); | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + /** | ||
| 216 | + * Checks whether exception is thrown when key leaf-list identifier is not found in list. | ||
| 217 | + */ | ||
| 218 | + @Test | ||
| 219 | + public void processInvalidLeafListIdentifier() throws IOException, ParserException { | ||
| 220 | + thrown.expect(ParserException.class); | ||
| 221 | + thrown.expectMessage("Leaf-list identifier must refer to a child leaf of the list"); | ||
| 222 | + YangNode node = manager.getDataModel("src/test/resources/InvalidLeafListIdentifier.yang"); | ||
| 223 | + } | ||
| 224 | + | ||
| 225 | + /** | ||
| 226 | + * Checks whether exception is thrown when key leaf-list is of type empty. | ||
| 227 | + */ | ||
| 228 | + @Test | ||
| 229 | + public void processKeyLeafListTypeEmpty() throws IOException, ParserException { | ||
| 230 | + thrown.expect(ParserException.class); | ||
| 231 | + thrown.expectMessage("A leaf-list that is part of the key must not be the built-in type \"empty\"."); | ||
| 232 | + YangNode node = manager.getDataModel("src/test/resources/KeyLeafListTypeEmpty.yang"); | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + /** | ||
| 236 | + * Checks whether exception is thrown when key leaf is of type empty. | ||
| 237 | + */ | ||
| 238 | + @Test | ||
| 239 | + public void processKeyLeafTypeEmpty() throws IOException, ParserException { | ||
| 240 | + thrown.expect(ParserException.class); | ||
| 241 | + thrown.expectMessage("A leaf that is part of the key must not be the built-in type \"empty\"."); | ||
| 242 | + YangNode node = manager.getDataModel("src/test/resources/KeyLeafTypeEmpty.yang"); | ||
| 243 | + } | ||
| 107 | } | 244 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -68,7 +68,7 @@ public class ListListenerTest { | ... | @@ -68,7 +68,7 @@ public class ListListenerTest { |
| 68 | assertThat(yangList.getName(), is("valid")); | 68 | assertThat(yangList.getName(), is("valid")); |
| 69 | 69 | ||
| 70 | ListIterator<String> keyList = yangList.getKeyList().listIterator(); | 70 | ListIterator<String> keyList = yangList.getKeyList().listIterator(); |
| 71 | - assertThat(keyList.next(), is("invalid")); | 71 | + assertThat(keyList.next(), is("invalid-interval")); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | /** | 74 | /** |
| ... | @@ -95,7 +95,7 @@ public class ListListenerTest { | ... | @@ -95,7 +95,7 @@ public class ListListenerTest { |
| 95 | // Check whether the list is child of container | 95 | // Check whether the list is child of container |
| 96 | YangList yangList = (YangList) yangContainer.getChild(); | 96 | YangList yangList = (YangList) yangContainer.getChild(); |
| 97 | assertThat(yangList.getName(), is("valid")); | 97 | assertThat(yangList.getName(), is("valid")); |
| 98 | - assertThat(yangList.getKeyList().contains("invalid"), is(true)); | 98 | + assertThat(yangList.getKeyList().contains("invalid-interval"), is(true)); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | /** | 101 | /** |
| ... | @@ -123,7 +123,7 @@ public class ListListenerTest { | ... | @@ -123,7 +123,7 @@ public class ListListenerTest { |
| 123 | // Check whether the list is child of list | 123 | // Check whether the list is child of list |
| 124 | YangList yangList = (YangList) yangList1.getChild(); | 124 | YangList yangList = (YangList) yangList1.getChild(); |
| 125 | assertThat(yangList.getName(), is("valid")); | 125 | assertThat(yangList.getName(), is("valid")); |
| 126 | - assertThat(yangList.getKeyList().contains("invalid"), is(true)); | 126 | + assertThat(yangList.getKeyList().contains("invalid-interval"), is(true)); |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | /** | 129 | /** |
| ... | @@ -148,7 +148,7 @@ public class ListListenerTest { | ... | @@ -148,7 +148,7 @@ public class ListListenerTest { |
| 148 | 148 | ||
| 149 | // Check whether list properties as set correctly. | 149 | // Check whether list properties as set correctly. |
| 150 | assertThat(yangList.getName(), is("ospf")); | 150 | assertThat(yangList.getName(), is("ospf")); |
| 151 | - assertThat(yangList.getKeyList().contains("process-id"), is(true)); | 151 | + assertThat(yangList.getKeyList().contains("invalid-interval"), is(true)); |
| 152 | 152 | ||
| 153 | assertThat(yangList.isConfig(), is(true)); | 153 | assertThat(yangList.isConfig(), is(true)); |
| 154 | assertThat(yangList.getMaxElelements(), is(10)); | 154 | assertThat(yangList.getMaxElelements(), is(10)); | ... | ... |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + container valid { | ||
| 6 | + leaf invalid-interval { | ||
| 7 | + type "uint16"; | ||
| 8 | + units "seconds"; | ||
| 9 | + description "Interval before a route is declared invalid"; | ||
| 10 | + mandatory true; | ||
| 11 | + status current; | ||
| 12 | + reference "RFC 6020"; | ||
| 13 | + } | ||
| 14 | + } | ||
| 15 | +} |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + container valid { | ||
| 6 | + config false; | ||
| 7 | + list valid { | ||
| 8 | + key "invalid-interval"; | ||
| 9 | + config true; | ||
| 10 | + leaf invalid-interval { | ||
| 11 | + type "uint16"; | ||
| 12 | + units "seconds"; | ||
| 13 | + status current; | ||
| 14 | + reference "RFC 6020"; | ||
| 15 | + } | ||
| 16 | + } | ||
| 17 | + } | ||
| 18 | +} |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + config false; | ||
| 7 | + key "invalid-interval"; | ||
| 8 | + leaf invalid-interval { | ||
| 9 | + type "uint16"; | ||
| 10 | + units "seconds"; | ||
| 11 | + status current; | ||
| 12 | + reference "RFC 6020"; | ||
| 13 | + } | ||
| 14 | + container valid { | ||
| 15 | + config true; | ||
| 16 | + leaf invalid-interval { | ||
| 17 | + type "uint16"; | ||
| 18 | + units "seconds"; | ||
| 19 | + status current; | ||
| 20 | + reference "RFC 6020"; | ||
| 21 | + } | ||
| 22 | + } | ||
| 23 | + } | ||
| 24 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + key "invalid-interval"; | ||
| 7 | + config false; | ||
| 8 | + leaf invalid-interval { | ||
| 9 | + type "uint16"; | ||
| 10 | + config true; | ||
| 11 | + units "seconds"; | ||
| 12 | + status current; | ||
| 13 | + reference "RFC 6020"; | ||
| 14 | + } | ||
| 15 | + } | ||
| 16 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + key "invalid-interval"; | ||
| 7 | + config false; | ||
| 8 | + leaf-list invalid-interval { | ||
| 9 | + type "uint16"; | ||
| 10 | + config true; | ||
| 11 | + units "seconds"; | ||
| 12 | + status current; | ||
| 13 | + reference "RFC 6020"; | ||
| 14 | + } | ||
| 15 | + } | ||
| 16 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + key "invalid-interval"; | ||
| 7 | + config false; | ||
| 8 | + leaf invalid-interval { | ||
| 9 | + type "string"; | ||
| 10 | + units "seconds"; | ||
| 11 | + status current; | ||
| 12 | + reference "RFC 6020"; | ||
| 13 | + } | ||
| 14 | + } | ||
| 15 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + key "invalid-interval"; | ||
| 7 | + leaf-list invalid-interval { | ||
| 8 | + type "string"; | ||
| 9 | + units "seconds"; | ||
| 10 | + status current; | ||
| 11 | + reference "RFC 6020"; | ||
| 12 | + } | ||
| 13 | + } | ||
| 14 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + config true; | ||
| 7 | + leaf invalid-interval { | ||
| 8 | + type "string"; | ||
| 9 | + units "seconds"; | ||
| 10 | + status current; | ||
| 11 | + reference "RFC 6020"; | ||
| 12 | + } | ||
| 13 | + } | ||
| 14 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + key "invalid-interval"; | ||
| 7 | + leaf-list invalid-interval { | ||
| 8 | + type "string"; | ||
| 9 | + units "seconds"; | ||
| 10 | + status current; | ||
| 11 | + reference "RFC 6020"; | ||
| 12 | + } | ||
| 13 | + } | ||
| 14 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -4,7 +4,7 @@ module Test { | ... | @@ -4,7 +4,7 @@ module Test { |
| 4 | prefix Ant; | 4 | prefix Ant; |
| 5 | container ospf { | 5 | container ospf { |
| 6 | list valid { | 6 | list valid { |
| 7 | - key "invalid"; | 7 | + key "invalid-interval"; |
| 8 | leaf invalid-interval { | 8 | leaf invalid-interval { |
| 9 | type "uint16"; | 9 | type "uint16"; |
| 10 | units "seconds"; | 10 | units "seconds"; | ... | ... |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + key "invalid-interval"; | ||
| 7 | + leaf invalid { | ||
| 8 | + type "string"; | ||
| 9 | + units "seconds"; | ||
| 10 | + status current; | ||
| 11 | + reference "RFC 6020"; | ||
| 12 | + } | ||
| 13 | + } | ||
| 14 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + key "invalid-interval"; | ||
| 7 | + leaf-list invalid { | ||
| 8 | + type "string"; | ||
| 9 | + units "seconds"; | ||
| 10 | + status current; | ||
| 11 | + reference "RFC 6020"; | ||
| 12 | + } | ||
| 13 | + } | ||
| 14 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + key "invalid-interval"; | ||
| 7 | + leaf-list invalid-interval { | ||
| 8 | + type "empty"; | ||
| 9 | + units "seconds"; | ||
| 10 | + status current; | ||
| 11 | + reference "RFC 6020"; | ||
| 12 | + } | ||
| 13 | + } | ||
| 14 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + key "invalid-interval"; | ||
| 7 | + leaf invalid-interval { | ||
| 8 | + type "empty"; | ||
| 9 | + units "seconds"; | ||
| 10 | + status current; | ||
| 11 | + reference "RFC 6020"; | ||
| 12 | + } | ||
| 13 | + } | ||
| 14 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -5,7 +5,7 @@ module Test { | ... | @@ -5,7 +5,7 @@ module Test { |
| 5 | list ospf { | 5 | list ospf { |
| 6 | key "process-id"; | 6 | key "process-id"; |
| 7 | list valid { | 7 | list valid { |
| 8 | - key "invalid"; | 8 | + key "invalid-interval"; |
| 9 | leaf invalid-interval { | 9 | leaf invalid-interval { |
| 10 | type "uint16"; | 10 | type "uint16"; |
| 11 | units "seconds"; | 11 | units "seconds"; |
| ... | @@ -13,5 +13,8 @@ module Test { | ... | @@ -13,5 +13,8 @@ module Test { |
| 13 | reference "RFC 6020"; | 13 | reference "RFC 6020"; |
| 14 | } | 14 | } |
| 15 | } | 15 | } |
| 16 | + leaf process-id { | ||
| 17 | + type "string"; | ||
| 18 | + } | ||
| 16 | } | 19 | } |
| 17 | } | 20 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -3,7 +3,7 @@ module Test { | ... | @@ -3,7 +3,7 @@ module Test { |
| 3 | namespace http://huawei.com; | 3 | namespace http://huawei.com; |
| 4 | prefix Ant; | 4 | prefix Ant; |
| 5 | list ospf { | 5 | list ospf { |
| 6 | - key "process-id"; | 6 | + key "invalid-interval"; |
| 7 | config true; | 7 | config true; |
| 8 | max-elements 10; | 8 | max-elements 10; |
| 9 | min-elements 3; | 9 | min-elements 3; | ... | ... |
| ... | @@ -3,7 +3,7 @@ module Test { | ... | @@ -3,7 +3,7 @@ module Test { |
| 3 | namespace http://huawei.com; | 3 | namespace http://huawei.com; |
| 4 | prefix Ant; | 4 | prefix Ant; |
| 5 | list valid { | 5 | list valid { |
| 6 | - key "invalid"; | 6 | + key "invalid-interval"; |
| 7 | leaf invalid-interval { | 7 | leaf invalid-interval { |
| 8 | type "uint16"; | 8 | type "uint16"; |
| 9 | units "seconds"; | 9 | units "seconds"; | ... | ... |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + container hello { | ||
| 6 | + container valid { | ||
| 7 | + leaf invalid-interval { | ||
| 8 | + type "uint16"; | ||
| 9 | + units "seconds"; | ||
| 10 | + status current; | ||
| 11 | + reference "RFC 6020"; | ||
| 12 | + } | ||
| 13 | + } | ||
| 14 | + } | ||
| 15 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + container valid { | ||
| 6 | + leaf invalid-interval { | ||
| 7 | + type "uint16"; | ||
| 8 | + units "seconds"; | ||
| 9 | + status current; | ||
| 10 | + reference "RFC 6020"; | ||
| 11 | + } | ||
| 12 | + } | ||
| 13 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + container valid { | ||
| 6 | + leaf-list invalid-interval { | ||
| 7 | + type "uint16"; | ||
| 8 | + units "seconds"; | ||
| 9 | + status current; | ||
| 10 | + reference "RFC 6020"; | ||
| 11 | + } | ||
| 12 | + } | ||
| 13 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + container hello { | ||
| 6 | + list valid { | ||
| 7 | + key "invalid-interval"; | ||
| 8 | + leaf invalid-interval { | ||
| 9 | + type "uint16"; | ||
| 10 | + units "seconds"; | ||
| 11 | + status current; | ||
| 12 | + reference "RFC 6020"; | ||
| 13 | + } | ||
| 14 | + } | ||
| 15 | + } | ||
| 16 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list list1 { | ||
| 6 | + key "invalid-interval"; | ||
| 7 | + leaf invalid-interval { | ||
| 8 | + type "uint16"; | ||
| 9 | + units "seconds"; | ||
| 10 | + status current; | ||
| 11 | + reference "RFC 6020"; | ||
| 12 | + } | ||
| 13 | + container container1 { | ||
| 14 | + leaf leaf1 { | ||
| 15 | + type "uint16"; | ||
| 16 | + units "seconds"; | ||
| 17 | + status current; | ||
| 18 | + reference "RFC 6020"; | ||
| 19 | + } | ||
| 20 | + } | ||
| 21 | + } | ||
| 22 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + key "invalid-interval"; | ||
| 7 | + leaf invalid-interval { | ||
| 8 | + type "uint16"; | ||
| 9 | + units "seconds"; | ||
| 10 | + status current; | ||
| 11 | + reference "RFC 6020"; | ||
| 12 | + } | ||
| 13 | + } | ||
| 14 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + key "invalid-interval"; | ||
| 7 | + leaf-list invalid-interval { | ||
| 8 | + type "uint16"; | ||
| 9 | + units "seconds"; | ||
| 10 | + status current; | ||
| 11 | + reference "RFC 6020"; | ||
| 12 | + } | ||
| 13 | + } | ||
| 14 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +module Test { | ||
| 2 | + yang-version 1; | ||
| 3 | + namespace http://huawei.com; | ||
| 4 | + prefix Ant; | ||
| 5 | + list valid { | ||
| 6 | + key "invalid-interval"; | ||
| 7 | + leaf invalid-interval { | ||
| 8 | + type "uint16"; | ||
| 9 | + units "seconds"; | ||
| 10 | + status current; | ||
| 11 | + reference "RFC 6020"; | ||
| 12 | + } | ||
| 13 | + list list1 { | ||
| 14 | + key "leaf1"; | ||
| 15 | + leaf leaf1 { | ||
| 16 | + type "uint16"; | ||
| 17 | + units "seconds"; | ||
| 18 | + status current; | ||
| 19 | + reference "RFC 6020"; | ||
| 20 | + } | ||
| 21 | + } | ||
| 22 | + } | ||
| 23 | +} |
-
Please register or login to post a comment