1 package org.apache.maven.doxia.module.confluence;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.FilterWriter;
23 import java.io.IOException;
24 import java.io.Reader;
25 import java.io.StringReader;
26 import java.io.StringWriter;
27 import java.io.Writer;
28 import java.util.Iterator;
29
30 import org.apache.maven.doxia.parser.AbstractParserTest;
31 import org.apache.maven.doxia.parser.ParseException;
32 import org.apache.maven.doxia.parser.Parser;
33 import org.apache.maven.doxia.sink.Sink;
34 import org.apache.maven.doxia.sink.SinkEventAttributeSet;
35 import org.apache.maven.doxia.sink.SinkEventElement;
36 import org.apache.maven.doxia.sink.SinkEventTestingSink;
37 import org.apache.maven.doxia.sink.TextSink;
38
39 import org.codehaus.plexus.util.IOUtil;
40 import org.codehaus.plexus.util.StringUtils;
41
42
43
44
45 public class ConfluenceParserTest
46 extends AbstractParserTest
47 {
48 private ConfluenceParser parser;
49
50 private StringWriter output;
51
52 private Reader reader;
53
54 private Writer writer;
55
56
57 protected void setUp()
58 throws Exception
59 {
60 super.setUp();
61
62 parser = (ConfluenceParser) lookup( Parser.ROLE, "confluence" );
63
64 output = null;
65 reader = null;
66 writer = null;
67 }
68
69
70 protected void tearDown()
71 throws Exception
72 {
73 IOUtil.close( output );
74 IOUtil.close( reader );
75 IOUtil.close( writer );
76
77 super.tearDown();
78 }
79
80
81 protected Parser createParser()
82 {
83 return parser;
84 }
85
86
87 protected String outputExtension()
88 {
89 return "confluence";
90 }
91
92
93 public void testMarkupTestPage()
94 throws Exception
95 {
96 String result = locateAndParseTestSourceFile( "test" );
97 assertContainsLines( result, "end:body" );
98 }
99
100
101 public void testParagraphWithSimpleFormatting()
102 throws Exception
103 {
104 String result = locateAndParseTestSourceFile( "simple-paragraph" );
105
106 assertContainsLines( result, "begin:bold\ntext: bold\n" );
107 assertContainsLines( result, "begin:italic\ntext: italic\n" );
108 assertContainsLines( result, "begin:monospaced\ntext: monospaced\n" );
109 assertContainsLines( result, "begin:link, name: http://jira.codehaus.org\ntext: http://jira.codehaus.org" );
110 assertContainsLines( result, "begin:link, name: http://jira.codehaus.org\ntext: JIRA\n" );
111
112 assertEquals( 5, result.split( "end:paragraph" ).length );
113 }
114
115
116 public void testLineBreak()
117 throws Exception
118 {
119 String lineBreak = getLineBreakString();
120
121 String result = locateAndParseTestSourceFile( "linebreak" );
122
123 assertContainsLines( result, "Line\n" + lineBreak );
124 assertContainsLines( result, "with 2\n" + lineBreak );
125 assertContainsLines( result, "inline\n" + lineBreak );
126 }
127
128
129 public void testEscapes()
130 throws Exception
131 {
132 String result = locateAndParseTestSourceFile( "escapes" );
133
134 assertContainsLines( result, "asterisk *" );
135 assertContainsLines( result, "underline _" );
136 assertContainsLines( result, "asterisk *not bold*" );
137 assertContainsLines( result, "underline _not italic_" );
138 assertContainsLines( result, "normal character" );
139 assertContainsLines( result, "trailing slash\\\n" );
140 }
141
142
143 public void testSectionTitles()
144 throws Exception
145 {
146 String result = locateAndParseTestSourceFile( "section" );
147
148 for ( int i = 1; i <= 5; i++ )
149 {
150 assertContainsLines( "Could not locate section " + i + " title", result,
151 "sectionTitle" + i + "\ntext: Section" + i );
152 }
153
154 assertContainsLines( "Section title has leading space", result, "sectionTitle1\ntext: TitleWithLeadingSpace" );
155 }
156
157
158 public void testNestedBulletList()
159 throws Exception
160 {
161 String result = locateAndParseTestSourceFile( "nested-list" );
162
163 assertContainsLines( "Nested list not found", result,
164 "begin:listItem\ntext: A top level list item\nbegin:list" );
165
166 assertEquals( 3, result.split( "end:list\n" ).length );
167
168 assertEquals( 5, result.split( "end:listItem\n" ).length );
169 }
170
171
172 public void testNestedHeterogenousList()
173 throws Exception
174 {
175 String result = locateAndParseTestSourceFile( "nested-list-heterogenous" );
176
177
178 assertContainsLines( "Nested list not found", result, "begin:listItem\ntext: A top level list item\nbegin:numberedList" );
179
180
181 assertEquals( 2, result.split( "begin:list\n" ).length );
182 assertEquals( 2, result.split( "begin:numberedList" ).length );
183
184
185 assertEquals( 5, result.split( "end:listItem\n" ).length );
186 }
187
188
189 public void testListWithSimpleFormatting()
190 throws Exception
191 {
192 String result = locateAndParseTestSourceFile( "simple-list" );
193
194 assertContainsLines( result, "begin:bold\ntext: bold\n" );
195 assertContainsLines( result, "begin:italic\ntext: italic\n" );
196 assertContainsLines( result, "begin:monospaced\ntext: monospaced\n" );
197 assertContainsLines( result, "begin:monospaced\ntext: some escaped monospaced \\\\unc\\path\n" );
198 assertContainsLines( result, "begin:link, name: http://jira.codehaus.org\ntext: http://jira.codehaus.org\n" );
199 assertContainsLines( result, "begin:link, name: http://jira.codehaus.org\ntext: JIRA\n" );
200 assertContainsLines( result, "begin:listItem\ntext: Item with no formatting\nend:listItem\n" );
201 assertContainsLines( result, "begin:listItem\ntext: One bullet\nend:listItem\n" );
202 assertContainsLines( result, "begin:listItem\ntext: A list item with more than one line\nend:listItem\n" );
203
204 assertEquals( 4, result.split( "end:list\n" ).length );
205
206 assertEquals( 9, result.split( "end:listItem\n" ).length );
207 }
208
209
210 public void testAnchor()
211 throws Exception
212 {
213 String result = locateAndParseTestSourceFile( "anchor" );
214
215 assertContainsLines( result, "begin:paragraph\nbegin:anchor, name: start\nend:anchor" );
216 assertContainsLines( result, "begin:anchor, name: middle\nend:anchor" );
217 assertContainsLines( result, "begin:paragraph\ntext: Simple paragraph\nbegin:anchor, name: end\nend:anchor" );
218
219 assertEquals( 4, result.split( "end:anchor\n" ).length );
220 }
221
222
223 public void testUnknownMacro()
224 throws Exception
225 {
226 String result = locateAndParseTestSourceFile( "unknown-macro" );
227
228 assertContainsLines( result, "begin:paragraph\ntext: {unknown:start}" );
229 }
230
231
232 public void testCodeMacro()
233 throws Exception
234 {
235 String result = locateAndParseTestSourceFile( "code" );
236
237 assertContainsLines( result, "begin:verbatim, boxed: true\ntext: public class Cat {" );
238
239 assertEquals( 5, result.split( "end:paragraph\n" ).length );
240
241 assertEquals( 3, result.split( "end:verbatim\n" ).length );
242 }
243
244
245 public void testFigure()
246 throws Exception
247 {
248 Reader result = getTestReader( "figure" );
249
250 SinkEventTestingSink sink = new SinkEventTestingSink();
251
252 parser.parse( result, sink );
253
254 Iterator<SinkEventElement> it = sink.getEventList().iterator();
255
256 assertEquals( it, "head", "head_", "body", "paragraph" );
257 assertEquals( it.next(), "text", "Simple paragraph." );
258 assertEquals( it, "paragraph_", "figure" );
259 assertEquals( it.next(), "figureGraphics", "images/photo.jpg" );
260 assertEquals( it, "figure_", "paragraph" );
261 assertEquals( it.next(), "text", "Simple paragraph with attempted inline !image.jpg! (should fail)." );
262 assertEquals( it, "paragraph_", "figure" );
263 assertEquals( it.next(), "figureGraphics", "images/photo.jpg" );
264 assertEquals( it.next().getName(), "figureCaption" );
265 assertEquals( it.next(), "text", "With caption on same line" );
266 assertEquals( it, "figureCaption_", "figure_", "figure" );
267 assertEquals( it.next(), "figureGraphics", "images/linebreak.jpg" );
268 assertEquals( it.next().getName(), "figureCaption" );
269 assertEquals( it.next(), "text", "With caption underneath and linebreak" );
270 assertEquals( it, "figureCaption_", "figure_", "figure" );
271 assertEquals( it.next(), "figureGraphics", "images/nolinebreak.jpg" );
272 assertEquals( it.next().getName(), "figureCaption" );
273 assertEquals( it.next(), "text", "With caption underneath and no linebreak" );
274 assertEquals( it, "figureCaption_", "figure_", "figure" );
275 assertEquals( it.next(), "figureGraphics", "images/bold.jpg" );
276 assertEquals( it.next().getName(), "figureCaption" );
277 assertEquals( it.next(), "text", "With *bold* caption underneath" );
278 assertEquals( it, "figureCaption_", "figure_", "figure" );
279 assertEquals( it.next(), "figureGraphics", "image.gif" );
280 assertEquals( it, "figure_", "body_" );
281 assertFalse( it.hasNext() );
282 }
283
284
285 public void testLink()
286 throws Exception
287 {
288 String result = locateAndParseTestSourceFile( "link" );
289
290 assertContainsLines( result, "begin:link, name: middle.html\ntext: middle\nend:link" );
291 assertContainsLines( result, "begin:link, name: end.html\ntext: end\nend:link" );
292 assertContainsLines( result, "begin:link, name: link.html\ntext: alias\nend:link" );
293 assertContainsLines( result, "begin:link, name: link.html#anchor\ntext: link#anchor\nend:link" );
294 assertContainsLines( result, "begin:link, name: #simple\ntext: simple\nend:link" );
295 assertContainsLines( result, "begin:link, name: resource.pdf\ntext: resource.pdf\nend:link" );
296 assertContainsLines( result, "begin:link, name: resource.pdf\ntext: alias pdf\nend:link" );
297 assertContainsLines( result, "begin:link, name: http://link.to/page_with_underscore-and-dash\ntext: underscore_-dash\nend:link" );
298
299 assertEquals( 6, result.split( "end:paragraph\n" ).length );
300
301 assertEquals( 9, result.split( "end:link\n" ).length );
302 }
303
304
305 public void testTableWithLinks()
306 throws Exception
307 {
308 String result = locateAndParseTestSourceFile( "table-link" );
309
310 assertContainsLines( result, "begin:tableCell\nbegin:link, name: http://example.com/release.0.1.3/ex-win32-win32.x86.zip\ntext: Download\nend:link\n\n\nend:tableCell\n" );
311 assertContainsLines( result, "begin:tableCell\nbegin:link, name: http://example.com/release.0.1.2/ex-win32-win32.x86.zip\ntext: http://example.com/release.0.1.2/ex-win32-win32.x86.zip\nend:link\n\n\nend:tableCell\n" );
312
313
314 assertEquals( 4, result.split( "end:link\n" ).length );
315 }
316
317
318 public void testParagraphWithList()
319 throws Exception
320 {
321 String result = locateAndParseTestSourceFile( "paragraph-list" );
322
323 assertContainsLines( result, "begin:paragraph\ntext: A paragraph\nend:paragraph\n" );
324 assertContainsLines( result, "begin:listItem\ntext: A nested list item\nend:listItem\n" );
325 assertContainsLines( result, "begin:listItem\ntext: Another nested list item with two lines\nend:listItem\n" );
326
327 assertEquals( 3, result.split( "end:paragraph\n" ).length );
328
329 assertEquals( 2, result.split( "end:list\n" ).length );
330 }
331
332
333 public void testParagraphWithFigure()
334 throws Exception
335 {
336 String result = locateAndParseTestSourceFile( "paragraph-figure" );
337
338 assertContainsLines( result, "begin:paragraph\ntext: A paragraph\nend:paragraph\n" );
339 assertContainsLines( result, "begin:figure\nfigureGraphics, name: images/logo.png\nbegin:figureCaption\ntext: with a figure\nend:figureCaption" );
340
341 assertEquals( 3, result.split( "end:paragraph\n" ).length );
342
343 assertEquals( 2, result.split( "end:figure\n" ).length );
344 }
345
346
347 public void testParagraphWithHeader()
348 throws Exception
349 {
350 String result = locateAndParseTestSourceFile( "paragraph-header" );
351
352 assertContainsLines( result, "begin:paragraph\ntext: A paragraph\nend:paragraph\n" );
353 assertContainsLines( result, "begin:section2\nbegin:sectionTitle2\ntext: A header\nend:sectionTitle2" );
354
355 assertEquals( 4, result.split( "end:paragraph\n" ).length );
356
357 assertEquals( 2, result.split( "end:sectionTitle2\n" ).length );
358 }
359
360
361 public void testNestedFormats()
362 throws Exception
363 {
364 String result = locateAndParseTestSourceFile( "nested-format" );
365
366 assertContainsLines( result, "begin:bold\nbegin:italic\ntext: bold italic\nend:italic" );
367 assertContainsLines( result, "begin:italic\nbegin:bold\ntext: italic bold\nend:bold" );
368 assertContainsLines( result, "begin:bold\nbegin:monospaced\ntext: bold monospaced\nend:monospaced" );
369 assertContainsLines( result, "text: A paragraph with \nbegin:bold\ntext: bold \nbegin:italic\ntext: italic\nend:italic" );
370 assertContainsLines( result, "begin:italic\ntext: italic \nbegin:bold\ntext: bold\nend:bold" );
371 assertContainsLines( result, "begin:bold\ntext: bold \nbegin:monospaced\ntext: monospaced\nend:monospaced" );
372
373 assertEquals( 3, result.split( "end:paragraph\n" ).length );
374
375 assertEquals( 7, result.split( "end:bold\n" ).length );
376
377 assertEquals( 5, result.split( "end:italic\n" ).length );
378
379 assertEquals( 3, result.split( "end:monospaced\n" ).length );
380 }
381
382
383 public void testNoteInfoTipQuote()
384 throws Exception
385 {
386 String result = locateAndParseTestSourceFile( "note-tip-info" );
387
388 assertContainsLines( result, "begin:definedTerm\ntext: Be Careful\nend:definedTerm\n" );
389 assertContainsLines( result, "begin:definition\ntext: The body of the note here..\nend:definition" );
390 assertContainsLines( result, "begin:definedTerm\ntext: Guess What?\nend:definedTerm\n" );
391 assertContainsLines( result, "begin:definition\ntext: The body of the tip here..\nend:definition" );
392 assertContainsLines( result, "begin:definedTerm\ntext: Some Info\nend:definedTerm\n" );
393 assertContainsLines( result, "begin:definition\ntext: The body of the info here..\nend:definition" );
394 assertContainsLines( result, "begin:definedTerm\ntext: Simon Says\nend:definedTerm\n" );
395 assertContainsLines( result, "begin:definition\ntext: The body of the \nbegin:bold\ntext: quote\nend:bold" );
396
397
398 assertEquals( 6, result.split( "end:paragraph\n" ).length );
399
400 assertEquals( 5, result.split( "end:definitionList\n" ).length );
401 }
402
403
404
405
406
407
408 public void testEndBracket()
409 throws ParseException
410 {
411 String document = "Test"
412 + "\n\n* list1"
413 + "\n\n* list2"
414 + "\n\n* list2"
415 + "\n{pre}123{/pre}";
416
417 output = new StringWriter();
418 Sink sink = new TextSink( output );
419
420
421 createParser().parse( new StringReader( document + " " ), sink );
422 assertTrue( "generated document should have a size > 0", output.toString().length() > 0 );
423
424
425 try
426 {
427 createParser().parse( new StringReader( document ), sink );
428 }
429 catch ( Exception e )
430 {
431 e.printStackTrace();
432 fail( "parsing with document ending in } should not fail" );
433 }
434
435 assertTrue( "generated document should have a size > 0", output.toString().length() > 0 );
436 }
437
438
439
440
441
442
443 public void testEndBracketInList()
444 throws ParseException
445 {
446 String document1 = "Test"
447 + "\n\n* list1"
448 + "\n\n* list2"
449 + "\n\n* list2{pre}123{/pre} "
450 + "\n123";
451
452 String document2 = "Test"
453 + "\n\n* list1"
454 + "\n\n* list2"
455 + "\n\n* list2{pre}123{/pre}"
456 + "\n123";
457
458 output = new StringWriter();
459 Sink sink = new TextSink( output );
460
461
462 createParser().parse( new StringReader( document1 ), sink );
463 assertTrue( "generated document should have a size > 0", output.toString().length() > 0 );
464
465
466 try
467 {
468 createParser().parse( new StringReader( document2 ), sink );
469 }
470 catch ( Exception e )
471 {
472 e.printStackTrace();
473 fail( "parsing with end of list item ending in } should not fail" );
474 }
475
476 assertTrue( "generated document should have a size > 0", output.toString().length() > 0 );
477 }
478
479 public void testDoxia382SinkCannotBeReused()
480 throws ParseException
481 {
482 String document1 = "Test A"
483 + "\n\n* list1"
484 + "\n\n* list2"
485 + "\n\n* list2{pre}123{/pre} "
486 + "\n123";
487
488 String document2 = "Test B"
489 + "\n\n* list1"
490 + "\n\n* list2"
491 + "\n\n* list2{pre}123{/pre}"
492 + "\n123";
493
494 output = new StringWriter();
495 Sink sink = new TextSink( new FilterWriter( output )
496 {
497 public void close() throws IOException
498 {
499 super.close();
500 this.out = null;
501 }
502
503 public void write( String str, int off, int len )
504 throws IOException
505 {
506 if ( out == null )
507 {
508 throw new IOException( "Writing to an already closed Writer" );
509 }
510 }
511 });
512
513 createParser().parse( new StringReader( document1 ), sink );
514 createParser().parse( new StringReader( document2 ), sink );
515 }
516
517
518
519
520
521
522
523 public void testSeparatorInParagraph()
524 throws ParseException
525 {
526 String document = "Up\n---\nDown\n";
527
528 output = new StringWriter();
529 Sink sink = new TextSink( output );
530
531
532 createParser().parse( new StringReader( document ), sink );
533 assertTrue( "generated document should have a size > 0", output.toString().length() > 0 );
534
535 }
536
537 public void testListFollowedByMacro() throws Exception
538 {
539
540
541 String document = "- This is a little test. \r\n" +
542 "\r\n" +
543 "{code}\r\n" +
544 " @Autowired\r\n" +
545 " private DataSource dataSource;\r\n" +
546 "{code}\r\n";
547 output = new StringWriter();
548 SinkEventTestingSink sink = new SinkEventTestingSink();
549 createParser().parse( new StringReader( document ), sink );
550
551 Iterator<SinkEventElement> it = sink.getEventList().iterator();
552 assertEquals("head", it.next().getName() );
553 assertEquals("head_", it.next().getName() );
554 assertEquals("body", it.next().getName() );
555 assertEquals("list", it.next().getName() );
556 assertEquals("listItem", it.next().getName() );
557 assertEquals( it.next(), "text", "This is a little test." );
558 assertEquals("listItem_", it.next().getName() );
559 assertEquals("list_", it.next().getName() );
560 assertEquals("verbatim", it.next().getName() );
561 assertEquals( it.next(), "text", " @Autowired\n private DataSource dataSource;\n" );
562 assertEquals("verbatim_", it.next().getName() );
563 assertEquals("body_", it.next().getName() );
564 }
565
566 public void testLinethrough() throws Exception {
567 String document = "-Linethrough-";
568 output = new StringWriter();
569 SinkEventTestingSink sink = new SinkEventTestingSink();
570 createParser().parse(new StringReader(document), sink);
571
572 Iterator<SinkEventElement> it = sink.getEventList().iterator();
573 assertEquals(it, "head", "head_", "body", "paragraph");
574 assertEquals(it.next(), "text", "Linethrough",
575 new SinkEventAttributeSet("decoration", "line-through"));
576 assertEquals(it, "paragraph_", "body_");
577 assertFalse(it.hasNext());
578 }
579
580 public void testUnderline() throws Exception {
581 String document = "+Underline+";
582 output = new StringWriter();
583 SinkEventTestingSink sink = new SinkEventTestingSink();
584 createParser().parse(new StringReader(document), sink);
585
586 Iterator<SinkEventElement> it = sink.getEventList().iterator();
587 assertEquals(it, "head", "head_", "body", "paragraph");
588 assertEquals(it.next(), "text", "Underline", new SinkEventAttributeSet(
589 "decoration", "underline"));
590 assertEquals(it, "paragraph_", "body_");
591 assertFalse(it.hasNext());
592 }
593
594 public void testSub() throws Exception {
595 String document = "~Sub~";
596 output = new StringWriter();
597 SinkEventTestingSink sink = new SinkEventTestingSink();
598 createParser().parse(new StringReader(document), sink);
599
600 Iterator<SinkEventElement> it = sink.getEventList().iterator();
601 assertEquals(it, "head", "head_", "body", "paragraph");
602 assertEquals(it.next(), "text", "Sub", new SinkEventAttributeSet(
603 "valign", "sub"));
604 assertEquals(it, "paragraph_", "body_");
605 assertFalse(it.hasNext());
606 }
607
608 public void testSup() throws Exception {
609 String document = "^Sup^";
610 output = new StringWriter();
611 SinkEventTestingSink sink = new SinkEventTestingSink();
612 createParser().parse(new StringReader(document), sink);
613
614 Iterator<SinkEventElement> it = sink.getEventList().iterator();
615 assertEquals(it, "head", "head_", "body", "paragraph");
616 assertEquals(it.next(), "text", "Sup", new SinkEventAttributeSet(
617 "valign", "sup"));
618 assertEquals(it, "paragraph_", "body_");
619 assertFalse(it.hasNext());
620 }
621
622 private void assertContainsLines( String message, String result, String lines )
623 {
624 lines = StringUtils.replace( lines, "\n", EOL );
625 if ( message != null )
626 {
627 assertTrue( message, result.indexOf( lines ) != -1 );
628 }
629 else
630 {
631 assertTrue( result.indexOf( lines ) != -1 );
632 }
633 }
634
635 private void assertContainsLines( String result, String lines )
636 {
637 this.assertContainsLines( null, result, lines );
638 }
639
640 private String getLineBreakString()
641 {
642 StringWriter sw = new StringWriter();
643 Sink sink = new TextSink( sw );
644 sink.lineBreak();
645
646 return sw.toString();
647 }
648
649 private String locateAndParseTestSourceFile( String stem )
650 throws IOException, ParseException
651 {
652 output = new StringWriter();
653 reader = getTestReader( stem, outputExtension() );
654 writer = getTestWriter( stem, "txt" );
655
656 Sink sink = new TextSink( output );
657 createParser().parse( reader, sink );
658
659
660 String expected = output.toString();
661 writer.write( expected );
662 writer.flush();
663 return expected;
664 }
665
666 }