001package org.apache.maven.doxia.module.confluence;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.FilterWriter;
023import java.io.IOException;
024import java.io.Reader;
025import java.io.StringReader;
026import java.io.StringWriter;
027import java.io.Writer;
028import java.util.Iterator;
029
030import org.apache.maven.doxia.parser.AbstractParserTest;
031import org.apache.maven.doxia.parser.ParseException;
032import org.apache.maven.doxia.parser.Parser;
033import org.apache.maven.doxia.sink.Sink;
034import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
035import org.apache.maven.doxia.sink.impl.SinkEventElement;
036import org.apache.maven.doxia.sink.impl.SinkEventTestingSink;
037import org.apache.maven.doxia.sink.impl.TextSink;
038import org.codehaus.plexus.util.IOUtil;
039import org.codehaus.plexus.util.StringUtils;
040
041/**
042 * Test class for ConfluenceParser.
043 */
044public class ConfluenceParserTest
045    extends AbstractParserTest
046{
047    private ConfluenceParser parser;
048
049    private StringWriter output;
050
051    private Reader reader;
052
053    private Writer writer;
054
055    /** {@inheritDoc} */
056    protected void setUp()
057        throws Exception
058    {
059        super.setUp();
060
061        parser = (ConfluenceParser) lookup( Parser.ROLE, "confluence" );
062
063        output = null;
064        reader = null;
065        writer = null;
066    }
067
068    /** {@inheritDoc} */
069    protected void tearDown()
070        throws Exception
071    {
072        IOUtil.close( output );
073        IOUtil.close( reader );
074        IOUtil.close( writer );
075
076        super.tearDown();
077    }
078
079    /** {@inheritDoc} */
080    protected Parser createParser()
081    {
082        return parser;
083    }
084
085    /** {@inheritDoc} */
086    protected String outputExtension()
087    {
088        return "confluence";
089    }
090
091    /** @throws Exception */
092    public void testMarkupTestPage()
093        throws Exception
094    {
095        String result = locateAndParseTestSourceFile( "test" );
096        assertContainsLines( result, "end:body" );
097    }
098
099    /** @throws Exception */
100    public void testParagraphWithSimpleFormatting()
101        throws Exception
102    {
103        String result = locateAndParseTestSourceFile( "simple-paragraph" );
104
105        assertContainsLines( result, "begin:bold\ntext: bold\n" );
106        assertContainsLines( result, "begin:italic\ntext: italic\n" );
107        assertContainsLines( result, "begin:monospaced\ntext: monospaced\n" );
108        assertContainsLines( result, "begin:link, name: http://jira.codehaus.org\ntext: http://jira.codehaus.org" );
109        assertContainsLines( result, "begin:link, name: http://jira.codehaus.org\ntext: JIRA\n" );
110        // four paragraphs in the input...
111        assertEquals( 5, result.split( "end:paragraph" ).length );
112    }
113
114    /** @throws Exception */
115    public void testLineBreak()
116        throws Exception
117    {
118        String lineBreak = getLineBreakString();
119
120        String result = locateAndParseTestSourceFile( "linebreak" );
121
122        assertContainsLines( result, "Line\n" + lineBreak );
123        assertContainsLines( result, "with 2\n" + lineBreak );
124        assertContainsLines( result, "inline\n" + lineBreak );
125    }
126
127    /** @throws Exception */
128    public void testEscapes()
129        throws Exception
130    {
131        String result = locateAndParseTestSourceFile( "escapes" );
132
133        assertContainsLines( result, "asterisk *" );
134        assertContainsLines( result, "underline _" );
135        assertContainsLines( result, "asterisk *not bold*" );
136        assertContainsLines( result, "underline _not italic_" );
137        assertContainsLines( result, "normal character" );
138        assertContainsLines( result, "trailing slash\\\n" );
139    }
140
141    /** @throws Exception */
142    public void testSectionTitles()
143        throws Exception
144    {
145        String result = locateAndParseTestSourceFile( "section" );
146
147        for ( int i = 1; i <= 5; i++ )
148        {
149            assertContainsLines( "Could not locate section " + i + " title", result,
150                    "sectionTitle" + i + "\ntext: Section" + i );
151        }
152
153        assertContainsLines( "Section title has leading space", result, "sectionTitle1\ntext: TitleWithLeadingSpace" );
154    }
155
156    /** @throws Exception */
157    public void testNestedBulletList()
158        throws Exception
159    {
160        String result = locateAndParseTestSourceFile( "nested-list" );
161
162        assertContainsLines( "Nested list not found", result,
163                "begin:listItem\ntext: A top level list item\nbegin:list" );
164        // two lists in the input...
165        assertEquals( 3, result.split( "end:list\n" ).length );
166        // ...and 4 list items
167        assertEquals( 5, result.split( "end:listItem\n" ).length );
168    }
169
170    /** @throws Exception */
171    public void testNestedHeterogenousList()
172        throws Exception
173    {
174        String result = locateAndParseTestSourceFile( "nested-list-heterogenous" );
175
176        // test heterogenous list
177        assertContainsLines( "Nested list not found", result, "begin:listItem\ntext: A top level list item\nbegin:numberedList" );
178
179        // exactly one list and one numberedList
180        assertEquals( 2, result.split( "begin:list\n" ).length );
181        assertEquals( 2, result.split( "begin:numberedList" ).length );
182
183        // ...and 4 list items
184        assertEquals( 5, result.split( "end:listItem\n" ).length );
185    }
186
187    /** @throws Exception */
188    public void testListWithSimpleFormatting()
189        throws Exception
190    {
191        String result = locateAndParseTestSourceFile( "simple-list" );
192
193        assertContainsLines( result, "begin:bold\ntext: bold\n" );
194        assertContainsLines( result, "begin:italic\ntext: italic\n" );
195        assertContainsLines( result, "begin:monospaced\ntext: monospaced\n" );
196        assertContainsLines( result, "begin:monospaced\ntext: some escaped monospaced \\\\unc\\path\n" );
197        assertContainsLines( result, "begin:link, name: http://jira.codehaus.org\ntext: http://jira.codehaus.org\n" );
198        assertContainsLines( result, "begin:link, name: http://jira.codehaus.org\ntext: JIRA\n" );
199        assertContainsLines( result, "begin:listItem\ntext: Item with no formatting\nend:listItem\n" );
200        assertContainsLines( result, "begin:listItem\ntext: One bullet\nend:listItem\n" );
201        assertContainsLines( result, "begin:listItem\ntext: A list item with more than one line\nend:listItem\n" );
202        // 3 lists in the input...
203        assertEquals( 4, result.split( "end:list\n" ).length );
204        // ...and 7 list items
205        assertEquals( 9, result.split( "end:listItem\n" ).length );
206    }
207
208    /** @throws Exception */
209    public void testAnchor()
210        throws Exception
211    {
212        String result = locateAndParseTestSourceFile( "anchor" );
213
214        assertContainsLines( result, "begin:paragraph\nbegin:anchor, name: start\nend:anchor" );
215        assertContainsLines( result, "begin:anchor, name: middle\nend:anchor" );
216        assertContainsLines( result, "begin:paragraph\ntext: Simple paragraph\nbegin:anchor, name: end\nend:anchor" );
217        // 3 anchors in the input...
218        assertEquals( 4, result.split( "end:anchor\n" ).length );
219    }
220
221    /** @throws Exception */
222    public void testUnknownMacro()
223        throws Exception
224    {
225        String result = locateAndParseTestSourceFile( "unknown-macro" );
226
227        assertContainsLines( result, "begin:paragraph\ntext: {unknown:start}" );
228    }
229
230    /** @throws Exception */
231    public void testCodeMacro()
232        throws Exception
233    {
234        String result = locateAndParseTestSourceFile( "code" );
235
236        assertContainsLines( result, "begin:verbatim, boxed: true\ntext: public class Cat {" );
237        // 5 paragraphs in the input...
238        assertEquals( 5, result.split( "end:paragraph\n" ).length );
239        // 3 verbatim in the input...
240        assertEquals( 3, result.split( "end:verbatim\n" ).length );
241    }
242
243    /** @throws Exception */
244    public void testFigure()
245        throws Exception
246    {
247        Reader result = getTestReader( "figure" );
248
249        SinkEventTestingSink sink = new SinkEventTestingSink();
250
251        parser.parse( result, sink );
252
253        Iterator<SinkEventElement> it = sink.getEventList().iterator();
254
255        assertStartsWith( it, "head", "head_", "body", "paragraph" );
256        assertEquals( it.next(), "text", "Simple paragraph." );
257        assertStartsWith( it, "paragraph_", "figure" );
258        assertEquals( it.next(), "figureGraphics", "images/photo.jpg" );
259        assertStartsWith( it, "figure_", "paragraph" );
260        assertEquals( it.next(), "text", "Simple paragraph with attempted inline !image.jpg! (should fail)." );
261        assertStartsWith( it, "paragraph_", "figure" );
262        assertEquals( it.next(), "figureGraphics", "images/photo.jpg" );
263        assertEquals( it.next().getName(), "figureCaption" ); 
264        assertEquals( it.next(), "text", "With caption on same line" );
265        assertStartsWith( it, "figureCaption_", "figure_", "figure" );
266        assertEquals( it.next(), "figureGraphics", "images/linebreak.jpg" );
267        assertEquals( it.next().getName(), "figureCaption" );
268        assertEquals( it.next(), "text", "With caption underneath and linebreak" );
269        assertStartsWith( it, "figureCaption_", "figure_", "figure" );
270        assertEquals( it.next(), "figureGraphics", "images/nolinebreak.jpg" );
271        assertEquals( it.next().getName(), "figureCaption" );
272        assertEquals( it.next(), "text", "With caption underneath and no linebreak" );
273        assertStartsWith( it, "figureCaption_", "figure_", "figure" );
274        assertEquals( it.next(), "figureGraphics", "images/bold.jpg" );
275        assertEquals( it.next().getName(), "figureCaption" );
276        assertEquals( it.next(), "text", "With *bold* caption underneath" );
277        assertStartsWith( it, "figureCaption_", "figure_", "figure" );
278        assertEquals( it.next(), "figureGraphics", "image.gif" );
279        assertEquals( it, "figure_", "body_" );
280    }
281
282    /** @throws Exception */
283    public void testLink()
284        throws Exception
285    {
286        String result = locateAndParseTestSourceFile( "link" );
287
288        assertContainsLines( result, "begin:link, name: middle.html\ntext: middle\nend:link" );
289        assertContainsLines( result, "begin:link, name: end.html\ntext: end\nend:link" );
290        assertContainsLines( result, "begin:link, name: link.html\ntext: alias\nend:link" );
291        assertContainsLines( result, "begin:link, name: link.html#anchor\ntext: link#anchor\nend:link" );
292        assertContainsLines( result, "begin:link, name: #simple\ntext: simple\nend:link" );
293        assertContainsLines( result, "begin:link, name: resource.pdf\ntext: resource.pdf\nend:link" );
294        assertContainsLines( result, "begin:link, name: resource.pdf\ntext: alias pdf\nend:link" );
295        assertContainsLines( result, "begin:link, name: http://link.to/page_with_underscore-and-dash\ntext: underscore_-dash\nend:link" );
296        // 5 paragraphs in the input...
297        assertEquals( 6, result.split( "end:paragraph\n" ).length );
298        // 8 links in the input...
299        assertEquals( 9, result.split( "end:link\n" ).length );
300    }
301
302    public void testTable()
303        throws Exception
304    {
305        String result = locateAndParseTestSourceFile( "table" );
306        
307        // DOXIA-537
308        // |1|2|3|
309        assertContainsLines( result, "begin:tableRow\nbegin:tableCell\ntext: 1\nend:tableCell\n\n\nbegin:tableCell\ntext: 2\nend:tableCell\n\n\nbegin:tableCell\ntext: 3\nend:tableCell\n" );
310        // |1||3|
311        assertContainsLines( result, "begin:tableRow\nbegin:tableCell\ntext: 1\nend:tableCell\n\n\nbegin:tableCell\ntext: 3\nend:tableCell\n" );
312        // |1| |3|
313        assertContainsLines( result, "begin:tableRow\nbegin:tableCell\ntext: 1\nend:tableCell\n\n\nbegin:tableCell\ntext:  \nend:tableCell\n\n\nbegin:tableCell\ntext: 3\nend:tableCell\n" );
314        
315    }
316
317    /** @throws Exception */
318    public void testTableWithLinks()
319        throws Exception
320    {
321        String result = locateAndParseTestSourceFile( "table-link" );
322
323        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" );
324        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" );
325
326        // 3 links in the input
327        assertEquals( 4, result.split( "end:link\n" ).length );
328    }
329
330    /** @throws Exception */
331    public void testTableWithImages()
332        throws Exception
333    {
334        // DOXIA-493
335        StringReader reader =
336            new StringReader( "Table containing image in cell:\n" + "\n" + "||Header 1||\n"
337                + "|!images/test/Image.png!|" );
338
339        SinkEventTestingSink sink = new SinkEventTestingSink();
340
341        parser.parse( reader, sink );
342
343        Iterator<SinkEventElement> it = sink.getEventList().iterator();
344
345        assertStartsWith( it, "head", "head_", "body", "paragraph" );
346        assertEquals( it.next(), "text", "Table containing image in cell:" );
347        assertStartsWith( it, "paragraph_", "table", "tableRows", "tableRow", "tableHeaderCell", "bold" );
348        assertEquals( it.next(), "text", "Header 1" );
349        assertStartsWith( it, "bold_", "tableHeaderCell_", "tableRow_", "tableRow", "tableCell", "figure" );
350        assertEquals( it.next(), "figureGraphics", "images/test/Image.png" );
351        assertEquals( it, "figure_", "tableCell_", "tableRow_", "tableRows_", "table_", "body_" );
352    }
353
354    /** @throws Exception */
355    public void testParagraphWithList()
356        throws Exception
357    {
358        String result = locateAndParseTestSourceFile( "paragraph-list" );
359
360        assertContainsLines( result, "begin:paragraph\ntext: A paragraph\nend:paragraph\n" );
361        assertContainsLines( result, "begin:listItem\ntext: A nested list item\nend:listItem\n" );
362        assertContainsLines( result, "begin:listItem\ntext: Another nested list item with two lines\nend:listItem\n" );
363        // 2 paragraphs in the input...
364        assertEquals( 3, result.split( "end:paragraph\n" ).length );
365        // 1 list in the input...
366        assertEquals( 2, result.split( "end:list\n" ).length );
367    }
368
369    /** @throws Exception */
370    public void testParagraphWithFigure()
371        throws Exception
372    {
373        String result = locateAndParseTestSourceFile( "paragraph-figure" );
374
375        assertContainsLines( result, "begin:paragraph\ntext: A paragraph\nend:paragraph\n" );
376        assertContainsLines( result, "begin:figure\nfigureGraphics, name: images/logo.png\nbegin:figureCaption\ntext: with a figure\nend:figureCaption" );
377        // 2 paragraphs in the input...
378        assertEquals( 3, result.split( "end:paragraph\n" ).length );
379        // 1 figure in the input...
380        assertEquals( 2, result.split( "end:figure\n" ).length );
381    }
382
383    /** @throws Exception */
384    public void testParagraphWithHeader()
385        throws Exception
386    {
387        String result = locateAndParseTestSourceFile( "paragraph-header" );
388
389        assertContainsLines( result, "begin:paragraph\ntext: A paragraph\nend:paragraph\n" );
390        assertContainsLines( result, "begin:section2\nbegin:sectionTitle2\ntext: A header\nend:sectionTitle2" );
391        // 3 paragraphs in the input...
392        assertEquals( 4, result.split( "end:paragraph\n" ).length );
393        // 1 header in the input...
394        assertEquals( 2, result.split( "end:sectionTitle2\n" ).length );
395    }
396
397    /** @throws Exception */
398    public void testNestedFormats()
399        throws Exception
400    {
401        String result = locateAndParseTestSourceFile( "nested-format" );
402
403        assertContainsLines( result, "begin:bold\nbegin:italic\ntext: bold italic\nend:italic" );
404        assertContainsLines( result, "begin:italic\nbegin:bold\ntext: italic bold\nend:bold" );
405        assertContainsLines( result, "begin:bold\nbegin:monospaced\ntext: bold monospaced\nend:monospaced" );
406        assertContainsLines( result, "text: A paragraph with \nbegin:bold\ntext: bold \nbegin:italic\ntext: italic\nend:italic" );
407        assertContainsLines( result, "begin:italic\ntext: italic \nbegin:bold\ntext: bold\nend:bold" );
408        assertContainsLines( result, "begin:bold\ntext: bold \nbegin:monospaced\ntext: monospaced\nend:monospaced" );
409        assertContainsLines( result, "begin:monospaced\ntext: monospaced-with-dashes\nend:monospaced");
410        assertContainsLines( result, "begin:monospaced\ntext: monospaced_with_underscores\nend:monospaced");
411        assertContainsLines( result, "begin:monospaced\ntext: monospaced*with*stars\nend:monospaced");
412        assertContainsLines( result, "begin:monospaced\ntext: monospaced+with+plus\nend:monospaced");
413        assertContainsLines( result, "begin:monospaced\ntext: monospaced~with~tilde\nend:monospaced");
414        assertContainsLines( result, "begin:monospaced\ntext: monospaced^with^circumflex^accent\nend:monospaced");
415        assertContainsLines( result, "begin:monospaced\ntext: monospaced[with]brackets\nend:monospaced");
416        assertContainsLines( result, "begin:monospaced\ntext: monospaced{with}curly{brackets\nend:monospaced");
417        assertContainsLines( result, "begin:monospaced\ntext: monospaced\\\\\\with\\\\backslashes\nend:monospaced");
418
419        // 3 paragraphs in the input...
420        assertEquals( 4, result.split( "end:paragraph\n" ).length );
421        // 6 bolds in the input...
422        assertEquals( 7, result.split( "end:bold\n" ).length );
423        // 4 italics in the input...
424        assertEquals( 5, result.split( "end:italic\n" ).length );
425        // 11 monospaced in the input...
426        assertEquals( 12, result.split( "end:monospaced\n" ).length );
427    }
428
429    /** @throws Exception */
430    public void testNoteInfoTipQuote()
431        throws Exception
432    {
433        String result = locateAndParseTestSourceFile( "note-tip-info" );
434
435        assertContainsLines( result, "begin:definedTerm\ntext: Be Careful\nend:definedTerm\n" );
436        assertContainsLines( result, "begin:definition\ntext: The body of the note here..\nend:definition" );
437        assertContainsLines( result, "begin:definedTerm\ntext: Guess What?\nend:definedTerm\n" );
438        assertContainsLines( result, "begin:definition\ntext: The body of the tip here..\nend:definition" );
439        assertContainsLines( result, "begin:definedTerm\ntext: Some Info\nend:definedTerm\n" );
440        assertContainsLines( result, "begin:definition\ntext: The body of the info here..\nend:definition" );
441        assertContainsLines( result, "begin:definedTerm\ntext: Simon Says\nend:definedTerm\n" );
442        assertContainsLines( result, "begin:definition\ntext: The body of the \nbegin:bold\ntext: quote\nend:bold" );
443
444        // 5 paragraphs in the input...
445        assertEquals( 6, result.split( "end:paragraph\n" ).length );
446        // 4 dinitionList in the input...
447        assertEquals( 5, result.split( "end:definitionList\n" ).length );
448    }
449
450    /**
451     * DOXIA-247
452     *
453     * @throws ParseException if something goes wrong.
454     */
455    public void testEndBracket()
456        throws ParseException
457    {
458        String document = "Test"
459            + "\n\n* list1"
460            + "\n\n* list2"
461            + "\n\n* list2"
462            + "\n{pre}123{/pre}";
463
464        output = new StringWriter();
465        Sink sink = new TextSink( output );
466
467        /* parsing with additional space at end works */
468        createParser().parse( new StringReader( document + " " ), sink );
469        assertTrue( "generated document should have a size > 0", output.toString().length() > 0 );
470
471        /* parsing with document ending in } should not fail */
472        try
473        {
474            createParser().parse( new StringReader( document ), sink );
475        }
476        catch ( Exception e )
477        {
478            e.printStackTrace();
479            fail( "parsing with document ending in } should not fail" );
480        }
481
482        assertTrue( "generated document should have a size > 0", output.toString().length() > 0 );
483    }
484
485    /**
486     * DOXIA-247
487     *
488     * @throws ParseException
489     */
490    public void testEndBracketInList()
491        throws ParseException
492    {
493        String document1 = "Test"
494            + "\n\n* list1"
495            + "\n\n* list2"
496            + "\n\n* list2{pre}123{/pre} "
497            + "\n123";
498
499        String document2 = "Test"
500            + "\n\n* list1"
501            + "\n\n* list2"
502            + "\n\n* list2{pre}123{/pre}"
503            + "\n123";
504
505        output = new StringWriter();
506        Sink sink = new TextSink( output );
507
508        /* parsing with additional space at end of list item works */
509        createParser().parse( new StringReader( document1 ), sink );
510        assertTrue( "generated document should have a size > 0", output.toString().length() > 0 );
511
512        /* parsing with end of list item ending in } should not fail */
513        try
514        {
515            createParser().parse( new StringReader( document2 ), sink );
516        }
517        catch ( Exception e )
518        {
519            e.printStackTrace();
520            fail( "parsing with end of list item ending in } should not fail" );
521        }
522
523        assertTrue( "generated document should have a size > 0", output.toString().length() > 0 );
524    }
525
526    public void testDoxia382SinkCannotBeReused()
527            throws ParseException
528    {
529        String document1 = "Test A"
530            + "\n\n* list1"
531            + "\n\n* list2"
532            + "\n\n* list2{pre}123{/pre} "
533            + "\n123";
534
535        String document2 = "Test B"
536            + "\n\n* list1"
537            + "\n\n* list2"
538            + "\n\n* list2{pre}123{/pre}"
539            + "\n123";
540
541        output = new StringWriter();
542        Sink sink = new TextSink( new FilterWriter( output )
543        {
544            public void close() throws IOException
545            {
546                super.close();
547                this.out = null;
548            }
549
550            public void write( String str, int off, int len )
551                    throws IOException
552            {
553                if ( out == null )
554                {
555                    throw new IOException( "Writing to an already closed Writer" );
556                }
557            }
558        });
559
560        createParser().parse( new StringReader( document1 ), sink );
561        createParser().parse( new StringReader( document2 ), sink );
562    }
563    
564
565    /**
566     * DOXIA-370
567     *
568     * @throws ParseException
569     */
570    public void testSeparatorInParagraph()
571        throws ParseException
572    {
573        String document = "Up\n---\nDown\n";
574
575        output = new StringWriter();
576        Sink sink = new TextSink( output );
577
578        /* parsing with separator in middle of paragraph */
579        createParser().parse( new StringReader( document ), sink );
580        assertTrue( "generated document should have a size > 0", output.toString().length() > 0 );
581
582    }
583    
584    public void testListFollowedByMacro() throws Exception
585    {
586        // @todo FIX
587        // DOXIA-371
588        String document = "- This is a little test. \r\n" +
589                "\r\n" + // with extra linebreak it succeeds, without it should too 
590                        "{code}\r\n" + 
591                        "    @Autowired\r\n" + 
592                        "    private DataSource dataSource;\r\n" + 
593                        "{code}\r\n"; 
594        output = new StringWriter();
595        SinkEventTestingSink sink = new SinkEventTestingSink();
596        createParser().parse( new StringReader( document ), sink );
597        
598        Iterator<SinkEventElement> it = sink.getEventList().iterator();
599        assertEquals("head", it.next().getName() );
600        assertEquals("head_", it.next().getName() );
601        assertEquals("body", it.next().getName() );
602        assertEquals("list", it.next().getName() );
603        assertEquals("listItem", it.next().getName() );
604        assertEquals( it.next(), "text", "This is a little test." );
605        assertEquals("listItem_", it.next().getName() );
606        assertEquals("list_", it.next().getName() );
607        assertEquals("verbatim", it.next().getName() );
608        assertEquals( it.next(), "text", "    @Autowired\n    private DataSource dataSource;\n" );
609        assertEquals("verbatim_", it.next().getName() );
610        assertEquals("body_", it.next().getName() );
611    }
612
613        public void testLinethrough() throws Exception {
614                String document = "-Linethrough-";
615                output = new StringWriter();
616                SinkEventTestingSink sink = new SinkEventTestingSink();
617                createParser().parse(new StringReader(document), sink);
618
619                Iterator<SinkEventElement> it = sink.getEventList().iterator();
620                assertStartsWith(it, "head", "head_", "body", "paragraph");
621                assertEquals(it.next(), "text", "Linethrough",
622                                new SinkEventAttributeSet("decoration", "line-through"));
623                assertEquals(it, "paragraph_", "body_");
624        }
625
626        public void testUnderline() throws Exception {
627                String document = "+Underline+";
628                output = new StringWriter();
629                SinkEventTestingSink sink = new SinkEventTestingSink();
630                createParser().parse(new StringReader(document), sink);
631
632                Iterator<SinkEventElement> it = sink.getEventList().iterator();
633                assertStartsWith(it, "head", "head_", "body", "paragraph");
634                assertEquals(it.next(), "text", "Underline", new SinkEventAttributeSet(
635                                "decoration", "underline"));
636                assertEquals(it, "paragraph_", "body_");
637        }
638
639        public void testSub() throws Exception {
640                String document = "~Sub~";
641                output = new StringWriter();
642                SinkEventTestingSink sink = new SinkEventTestingSink();
643                createParser().parse(new StringReader(document), sink);
644
645                Iterator<SinkEventElement> it = sink.getEventList().iterator();
646                assertStartsWith(it, "head", "head_", "body", "paragraph");
647                assertEquals(it.next(), "text", "Sub", new SinkEventAttributeSet(
648                                "valign", "sub"));
649                assertEquals(it, "paragraph_", "body_");
650        }
651
652        public void testSup() throws Exception {
653                String document = "^Sup^";
654                output = new StringWriter();
655                SinkEventTestingSink sink = new SinkEventTestingSink();
656                createParser().parse(new StringReader(document), sink);
657
658                Iterator<SinkEventElement> it = sink.getEventList().iterator();
659                assertStartsWith(it, "head", "head_", "body", "paragraph");
660                assertEquals(it.next(), "text", "Sup", new SinkEventAttributeSet(
661                                "valign", "sup"));
662                assertEquals(it, "paragraph_", "body_");
663        }
664
665    private void assertContainsLines( String message, String result, String lines )
666    {
667        lines = StringUtils.replace( lines, "\n", EOL );
668        if ( message != null )
669        {
670            assertTrue( message, result.indexOf( lines ) != -1 );
671        }
672        else
673        {
674            assertTrue( result.indexOf( lines ) != -1 );
675        }
676    }
677
678    private void assertContainsLines( String result, String lines )
679    {
680        this.assertContainsLines( null, result, lines );
681    }
682
683    private String getLineBreakString()
684    {
685        StringWriter sw = new StringWriter();
686        Sink sink = new TextSink( sw );
687        sink.lineBreak();
688
689        return sw.toString();
690    }
691
692    private String locateAndParseTestSourceFile( String stem )
693        throws IOException, ParseException
694    {
695        output = new StringWriter();
696        reader = getTestReader( stem, outputExtension() );
697        writer = getTestWriter( stem, "txt" );
698
699        Sink sink = new TextSink( output );
700        createParser().parse( reader, sink );
701
702        // write to file
703        String expected = output.toString();
704        writer.write( expected );
705        writer.flush();
706        return expected;
707    }
708
709}