1 /** 2 * Copyright (c) 2008, SnakeYAML 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 package org.yaml.snakeyaml.comment; 15 16 import static org.junit.Assert.assertEquals; 17 import static org.junit.Assert.assertTrue; 18 19 import java.io.ByteArrayOutputStream; 20 import java.io.PrintStream; 21 import java.util.ArrayList; 22 import java.util.Collections; 23 import java.util.LinkedHashMap; 24 import java.util.List; 25 import org.junit.Test; 26 import org.yaml.snakeyaml.comments.CommentLine; 27 import org.yaml.snakeyaml.composer.Composer; 28 import org.yaml.snakeyaml.constructor.SafeConstructor; 29 import org.yaml.snakeyaml.nodes.MappingNode; 30 import org.yaml.snakeyaml.nodes.Node; 31 import org.yaml.snakeyaml.nodes.NodeTuple; 32 import org.yaml.snakeyaml.nodes.ScalarNode; 33 import org.yaml.snakeyaml.nodes.SequenceNode; 34 import org.yaml.snakeyaml.parser.ParserImpl; 35 import org.yaml.snakeyaml.reader.StreamReader; 36 import org.yaml.snakeyaml.resolver.Resolver; 37 38 public class ComposerWithCommentEnabledTest { 39 40 private final boolean DEBUG = false; 41 printBlockComment(Node node, int level, PrintStream out)42 private void printBlockComment(Node node, int level, PrintStream out) { 43 if (node.getBlockComments() != null) { 44 List<CommentLine> blockComments = node.getBlockComments(); 45 for (int i = 0; i < blockComments.size(); i++) { 46 printWithIndent("Block Comment", level, out); 47 } 48 } 49 } 50 printEndComment(Node node, int level, PrintStream out)51 private void printEndComment(Node node, int level, PrintStream out) { 52 if (node.getEndComments() != null) { 53 List<CommentLine> endComments = node.getEndComments(); 54 for (int i = 0; i < endComments.size(); i++) { 55 printWithIndent("End Comment", level, out); 56 } 57 } 58 } 59 printInLineComment(Node node, int level, PrintStream out)60 private void printInLineComment(Node node, int level, PrintStream out) { 61 if (node.getInLineComments() != null) { 62 List<CommentLine> inLineComments = node.getInLineComments(); 63 for (int i = 0; i < inLineComments.size(); i++) { 64 printWithIndent("InLine Comment", level + 1, out); 65 } 66 } 67 } 68 printWithIndent(String line, int level, PrintStream out)69 private void printWithIndent(String line, int level, PrintStream out) { 70 for (int ix = 0; ix < level; ix++) { 71 out.print(" "); 72 } 73 out.print(line); 74 out.print("\n"); 75 } 76 printNodeInternal(Node node, int level, PrintStream out)77 private void printNodeInternal(Node node, int level, PrintStream out) { 78 79 if (node instanceof MappingNode) { 80 MappingNode mappingNode = (MappingNode) node; 81 printBlockComment(mappingNode, level, out); 82 printWithIndent(mappingNode.getClass().getSimpleName(), level, out); 83 for (NodeTuple childNodeTuple : mappingNode.getValue()) { 84 printWithIndent("Tuple", level + 1, out); 85 printNodeInternal(childNodeTuple.getKeyNode(), level + 2, out); 86 printNodeInternal(childNodeTuple.getValueNode(), level + 2, out); 87 } 88 printInLineComment(mappingNode, level, out); 89 printEndComment(mappingNode, level, out); 90 91 } else if (node instanceof SequenceNode) { 92 SequenceNode sequenceNode = (SequenceNode) node; 93 printBlockComment(sequenceNode, level, out); 94 printWithIndent(sequenceNode.getClass().getSimpleName(), level, out); 95 for (Node childNode : sequenceNode.getValue()) { 96 printNodeInternal(childNode, level + 1, out); 97 } 98 printInLineComment(sequenceNode, level, out); 99 printEndComment(sequenceNode, level, out); 100 101 } else if (node instanceof ScalarNode) { 102 ScalarNode scalarNode = (ScalarNode) node; 103 printBlockComment(scalarNode, level, out); 104 printWithIndent(scalarNode.getClass().getSimpleName() + ": " + scalarNode.getValue(), level, 105 out); 106 printInLineComment(scalarNode, level, out); 107 printEndComment(scalarNode, level, out); 108 109 } else { 110 printBlockComment(node, level, out); 111 printWithIndent(node.getClass().getSimpleName(), level, out); 112 printInLineComment(node, level, out); 113 printEndComment(node, level, out); 114 } 115 } 116 printNodeList(List<Node> nodeList)117 private void printNodeList(List<Node> nodeList) { 118 if (DEBUG) { 119 System.out.println("BEGIN"); 120 boolean first = true; 121 for (Node node : nodeList) { 122 if (first) { 123 first = false; 124 } else { 125 System.out.println("---"); 126 } 127 printNodeInternal(node, 1, System.out); 128 } 129 System.out.println("DONE\n"); 130 } 131 } 132 getNodeList(Composer composer)133 private List<Node> getNodeList(Composer composer) { 134 List<Node> nodeList = new ArrayList<>(); 135 while (composer.checkNode()) { 136 nodeList.add(composer.getNode()); 137 } 138 return nodeList; 139 } 140 assertNodesEqual(String[] expected, List<Node> nodeList)141 private void assertNodesEqual(String[] expected, List<Node> nodeList) { 142 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 143 boolean first = true; 144 try (PrintStream out = new PrintStream(baos)) { 145 for (Node node : nodeList) { 146 if (first) { 147 first = false; 148 } else { 149 out.print("---\n"); 150 } 151 printNodeInternal(node, 0, out); 152 } 153 } 154 String actualString = baos.toString(); 155 String[] actuals = actualString.split("\n"); 156 for (int ix = 0; ix < Math.min(expected.length, actuals.length); ix++) { 157 assertEquals(expected[ix], actuals[ix]); 158 } 159 assertEquals(expected.length, actuals.length); 160 } 161 newComposerWithCommentsEnabled(String data)162 public Composer newComposerWithCommentsEnabled(String data) { 163 return new Composer(new ParserImpl(new StreamReader(data), true), new Resolver()); 164 } 165 166 @Test testEmpty()167 public void testEmpty() { 168 String data = ""; 169 String[] expected = new String[] { // 170 "" // 171 }; 172 173 Composer sut = newComposerWithCommentsEnabled(data); 174 List<Node> result = getNodeList(sut); 175 176 printNodeList(result); 177 assertNodesEqual(expected, result); 178 } 179 180 @Test testParseWithOnlyComment()181 public void testParseWithOnlyComment() { 182 String data = "# Comment"; 183 String[] expected = new String[] { // 184 "Block Comment", // 185 "MappingNode", // 186 }; 187 188 Composer sut = newComposerWithCommentsEnabled(data); 189 List<Node> result = getNodeList(sut); 190 191 printNodeList(result); 192 assertNodesEqual(expected, result); 193 } 194 195 @Test testCommentEndingALine()196 public void testCommentEndingALine() { 197 String data = "" + // 198 "key: # Comment\n" + // 199 " value\n"; 200 201 String[] expected = new String[] { // 202 "MappingNode", // 203 " Tuple", // 204 " ScalarNode: key", // 205 " InLine Comment", // 206 " ScalarNode: value" // 207 }; 208 209 Composer sut = newComposerWithCommentsEnabled(data); 210 List<Node> result = getNodeList(sut); 211 212 printNodeList(result); 213 assertNodesEqual(expected, result); 214 } 215 216 @Test testMultiLineComment()217 public void testMultiLineComment() { 218 String data = "" + // 219 "key: # Comment\n" + // 220 " # lines\n" + // 221 " value\n" + // 222 "\n"; 223 224 String[] expected = new String[] { // 225 "MappingNode", // 226 " Tuple", // 227 " ScalarNode: key", // 228 " InLine Comment", // 229 " InLine Comment", // 230 " ScalarNode: value", // 231 "End Comment" // 232 }; 233 234 Composer sut = newComposerWithCommentsEnabled(data); 235 List<Node> result = getNodeList(sut); 236 237 printNodeList(result); 238 assertNodesEqual(expected, result); 239 } 240 241 @Test testBlankLine()242 public void testBlankLine() { 243 String data = "" + // 244 "\n"; 245 246 String[] expected = new String[] { // 247 "Block Comment", // 248 "MappingNode", // 249 }; 250 251 Composer sut = newComposerWithCommentsEnabled(data); 252 List<Node> result = getNodeList(sut); 253 254 printNodeList(result); 255 assertNodesEqual(expected, result); 256 } 257 258 @Test testBlankLineComments()259 public void testBlankLineComments() { 260 String data = "" + // 261 "\n" + // 262 "abc: def # commment\n" + // 263 "\n" + // 264 "\n"; 265 266 String[] expected = new String[] { // 267 "MappingNode", // 268 " Tuple", // 269 " Block Comment", // 270 " ScalarNode: abc", // 271 " ScalarNode: def", // 272 " InLine Comment", // 273 "End Comment", // 274 "End Comment", // 275 }; 276 277 Composer sut = newComposerWithCommentsEnabled(data); 278 List<Node> result = getNodeList(sut); 279 280 printNodeList(result); 281 assertNodesEqual(expected, result); 282 } 283 284 @Test test_blockScalar()285 public void test_blockScalar() { 286 String data = "" + // 287 "abc: > # Comment\n" + // 288 " def\n" + // 289 " hij\n" + // 290 "\n"; 291 292 String[] expected = new String[] { // 293 "MappingNode", // 294 " Tuple", // 295 " ScalarNode: abc", // 296 " InLine Comment", // 297 " ScalarNode: def hij" // 298 }; 299 300 Composer sut = newComposerWithCommentsEnabled(data); 301 List<Node> result = getNodeList(sut); 302 303 printNodeList(result); 304 assertNodesEqual(expected, result); 305 } 306 307 @Test testDirectiveLineEndComment()308 public void testDirectiveLineEndComment() { 309 String data = "%YAML 1.1 #Comment\n"; 310 311 String[] expected = new String[] { // 312 "" // 313 }; 314 315 Composer sut = newComposerWithCommentsEnabled(data); 316 List<Node> result = getNodeList(sut); 317 318 printNodeList(result); 319 assertNodesEqual(expected, result); 320 } 321 322 @Test testSequence()323 public void testSequence() { 324 String data = "" + // 325 "# Comment\n" + // 326 "list: # InlineComment1\n" + // 327 "# Block Comment\n" + // 328 "- item # InlineComment2\n" + // 329 "# Comment\n"; 330 331 String[] expected = new String[] { // 332 "MappingNode", // 333 " Tuple", // 334 " Block Comment", // 335 " ScalarNode: list", // 336 " InLine Comment", // 337 " SequenceNode", // 338 " Block Comment", // 339 " ScalarNode: item", // 340 " InLine Comment", // 341 "End Comment" // 342 }; 343 344 Composer sut = newComposerWithCommentsEnabled(data); 345 List<Node> result = getNodeList(sut); 346 347 printNodeList(result); 348 assertNodesEqual(expected, result); 349 } 350 351 @Test testAllComments1()352 public void testAllComments1() throws Exception { 353 String data = "" + // 354 "# Block Comment1\n" + // 355 "# Block Comment2\n" + // 356 "key: # Inline Comment1a\n" + // 357 " # Inline Comment1b\n" + // 358 " # Block Comment3a\n" + // 359 " # Block Comment3b\n" + // 360 " value # Inline Comment2\n" + // 361 "# Block Comment4\n" + // 362 "list: # InlineComment3a\n" + // 363 " # InlineComment3b\n" + // 364 "# Block Comment5\n" + // 365 "- item1 # InlineComment4\n" + // 366 "- item2: [ value2a, value2b ] # InlineComment5\n" + // 367 "- item3: { key3a: [ value3a1, value3a2 ], key3b: value3b } # InlineComment6\n" + // 368 "# Block Comment6\n" + // 369 "---\n" + // 370 "# Block Comment7\n" + // 371 ""; 372 373 String[] expected = new String[] { // 374 "MappingNode", // 375 " Tuple", // 376 " Block Comment", // 377 " Block Comment", // 378 " ScalarNode: key", // 379 " InLine Comment", // 380 " InLine Comment", // 381 " Block Comment", // 382 " Block Comment", // 383 " ScalarNode: value", // 384 " InLine Comment", // 385 " Tuple", // 386 " Block Comment", // 387 " ScalarNode: list", // 388 " InLine Comment", // 389 " InLine Comment", // 390 " SequenceNode", // 391 " Block Comment", // 392 " ScalarNode: item1", // 393 " InLine Comment", // 394 " MappingNode", // 395 " Tuple", // 396 " ScalarNode: item2", // 397 " SequenceNode", // 398 " ScalarNode: value2a", // 399 " ScalarNode: value2b", // 400 " InLine Comment", // 401 " MappingNode", // 402 " Tuple", // 403 " ScalarNode: item3", // 404 " MappingNode", // 405 " Tuple", // 406 " ScalarNode: key3a", // 407 " SequenceNode", // 408 " ScalarNode: value3a1", // 409 " ScalarNode: value3a2", // 410 " Tuple", // 411 " ScalarNode: key3b", // 412 " ScalarNode: value3b", // 413 " InLine Comment", // 414 "End Comment", // 415 "---", // 416 "Block Comment", // 417 "ScalarNode: ", // This is an empty scalar created as this is an empty document 418 }; 419 420 Composer sut = newComposerWithCommentsEnabled(data); 421 List<Node> result = getNodeList(sut); 422 423 printNodeList(result); 424 assertNodesEqual(expected, result); 425 } 426 427 @Test testAllComments2()428 public void testAllComments2() throws Exception { 429 String data = "" + // 430 "# Block Comment1\n" + // 431 "# Block Comment2\n" + // 432 "- item1 # Inline Comment1a\n" + // 433 " # Inline Comment1b\n" + // 434 "# Block Comment3a\n" + // 435 "# Block Comment3b\n" + // 436 "- item2: value # Inline Comment2\n" + // 437 "# Block Comment4\n" + // 438 ""; 439 440 String[] expected = new String[] { // 441 "SequenceNode", // 442 " Block Comment", // 443 " Block Comment", // 444 " ScalarNode: item1", // 445 " InLine Comment", // 446 " InLine Comment", // 447 " MappingNode", // 448 " Tuple", // 449 " Block Comment", // 450 " Block Comment", // 451 " ScalarNode: item2", // 452 " ScalarNode: value", // 453 " InLine Comment", // 454 "End Comment", // 455 }; 456 457 Composer sut = newComposerWithCommentsEnabled(data); 458 List<Node> result = getNodeList(sut); 459 460 printNodeList(result); 461 assertNodesEqual(expected, result); 462 } 463 464 @Test testAllComments3()465 public void testAllComments3() throws Exception { 466 String data = "" + // 467 "# Block Comment1\n" + // 468 "[ item1, item2: value2, {item3: value3} ] # Inline Comment1\n" + // 469 "# Block Comment2\n" + // 470 ""; 471 472 String[] expected = new String[] { // 473 "Block Comment", // 474 "SequenceNode", // 475 " ScalarNode: item1", // 476 " MappingNode", // 477 " Tuple", // 478 " ScalarNode: item2", // 479 " ScalarNode: value2", // 480 " MappingNode", // 481 " Tuple", // 482 " ScalarNode: item3", // 483 " ScalarNode: value3", // 484 " InLine Comment", // 485 "End Comment", // 486 }; 487 488 Composer sut = newComposerWithCommentsEnabled(data); 489 List<Node> result = getNodeList(sut); 490 491 printNodeList(result); 492 assertNodesEqual(expected, result); 493 } 494 495 @Test testGetSingleNode()496 public void testGetSingleNode() { 497 String data = "" + // 498 "\n" + // 499 "abc: def # commment\n" + // 500 "\n" + // 501 "\n"; 502 String[] expected = new String[] { // 503 "MappingNode", // 504 " Tuple", // 505 " Block Comment", " ScalarNode: abc", // 506 " ScalarNode: def", // 507 " InLine Comment", // 508 "End Comment", // 509 "End Comment", // 510 }; 511 512 Composer sut = newComposerWithCommentsEnabled(data); 513 List<Node> result = Collections.singletonList(sut.getSingleNode()); 514 515 printNodeList(result); 516 assertNodesEqual(expected, result); 517 } 518 519 @Test testGetSingleNodeHeaderComment()520 public void testGetSingleNodeHeaderComment() { 521 String data = "" + // 522 "\n" + // 523 "# Block Comment1\n" + // 524 "# Block Comment2\n" + // 525 "abc: def # commment\n" + // 526 "\n" + // 527 "\n"; 528 String[] expected = new String[] { // 529 "MappingNode", // 530 " Tuple", // 531 " Block Comment", // 532 " Block Comment", // 533 " Block Comment", // 534 " ScalarNode: abc", // 535 " ScalarNode: def", // 536 " InLine Comment", // 537 "End Comment", // 538 "End Comment", // 539 }; 540 541 Composer sut = newComposerWithCommentsEnabled(data); 542 List<Node> result = Collections.singletonList(sut.getSingleNode()); 543 544 printNodeList(result); 545 assertNodesEqual(expected, result); 546 } 547 548 private static class TestConstructor extends SafeConstructor { 549 550 } 551 552 @Test testBaseConstructorGetData()553 public void testBaseConstructorGetData() { 554 String data = "" + // 555 "\n" + // 556 "abc: def # commment\n" + // 557 "\n" + // 558 "\n"; 559 560 TestConstructor sut = new TestConstructor(); 561 sut.setComposer(newComposerWithCommentsEnabled(data)); 562 Object result = sut.getData(); 563 assertTrue(result instanceof LinkedHashMap); 564 @SuppressWarnings("unchecked") 565 LinkedHashMap<String, Object> map = (LinkedHashMap<String, Object>) result; 566 assertEquals(1, map.size()); 567 assertEquals(map.get("abc"), "def"); 568 } 569 570 @Test testEmptyEntryInMap()571 public void testEmptyEntryInMap() { 572 String data = "userProps:\n" + // 573 "#password\n" + // 574 "pass: mySecret\n"; 575 String[] expected = new String[] { // 576 "MappingNode", // 577 " Tuple", // 578 " ScalarNode: userProps", // 579 " ScalarNode: ", // 580 " Tuple", // 581 " Block Comment", // 582 " ScalarNode: pass", // 583 " ScalarNode: mySecret", // 584 }; 585 586 Composer sut = newComposerWithCommentsEnabled(data); 587 List<Node> result = Collections.singletonList(sut.getSingleNode()); 588 589 printNodeList(result); 590 assertNodesEqual(expected, result); 591 } 592 } 593