View Javadoc
1   package org.apache.maven.doxia.siterenderer;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static org.mockito.Matchers.eq;
23  import static org.mockito.Matchers.isNull;
24  import static org.mockito.Mockito.mock;
25  import static org.mockito.Mockito.verify;
26  import static org.mockito.Mockito.when;
27  
28  import java.io.File;
29  import java.io.FileOutputStream;
30  import java.io.FileReader;
31  import java.io.IOException;
32  import java.io.InputStream;
33  import java.io.OutputStream;
34  import java.io.Reader;
35  import java.io.StringWriter;
36  import java.io.Writer;
37  import java.util.Collections;
38  import java.util.HashMap;
39  import java.util.List;
40  import java.util.Locale;
41  import java.util.Map;
42  import java.util.jar.JarOutputStream;
43  import java.util.zip.ZipEntry;
44  
45  import org.apache.commons.io.IOUtils;
46  import org.apache.maven.doxia.site.decoration.DecorationModel;
47  import org.apache.maven.doxia.site.decoration.io.xpp3.DecorationXpp3Reader;
48  import org.apache.maven.doxia.siterenderer.sink.SiteRendererSink;
49  import org.apache.maven.doxia.xsd.AbstractXmlValidator;
50  import org.codehaus.plexus.PlexusTestCase;
51  import org.codehaus.plexus.util.FileUtils;
52  import org.codehaus.plexus.util.IOUtil;
53  import org.codehaus.plexus.util.ReaderFactory;
54  import org.codehaus.plexus.util.StringUtils;
55  import org.xml.sax.EntityResolver;
56  
57  /**
58   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
59   * @author <a href="mailto:evenisse@codehaus.org>Emmanuel Venisse</a>
60   * @version $Id: DefaultSiteRendererTest.java 1737482 2016-04-02 09:56:25Z hboutemy $
61   */
62  public class DefaultSiteRendererTest
63      extends PlexusTestCase
64  {
65      /**
66       * All output produced by this test will go here.
67       */
68      private static final String OUTPUT = "target/output";
69  
70      /**
71       * The renderer used to produce output.
72       */
73      private Renderer renderer;
74  
75      /**
76       * The locale before executing tests.
77       */
78      private Locale oldLocale;
79  
80      private File skinJar = new File( getBasedir(), "target/test-classes/skin.jar" );
81  
82      /**
83       * @throws java.lang.Exception if something goes wrong.
84       * @see org.codehaus.plexus.PlexusTestCase#setUp()
85       */
86      @Override
87      protected void setUp()
88          throws Exception
89      {
90          super.setUp();
91  
92          renderer = (Renderer) lookup( Renderer.ROLE );
93  
94          // copy the default-site.vm and default-site-macros.vm
95          copyVm( "default-site.vm", "\n\n\n\r\n\r\n\r\n" );
96          copyVm( "default-site-macros.vm", "" );
97  
98          InputStream skinIS = this.getResourceAsStream( "velocity-toolmanager.vm" );
99          JarOutputStream jarOS = new JarOutputStream( new FileOutputStream( skinJar ) );
100         try
101         {
102             jarOS.putNextEntry( new ZipEntry( "META-INF/maven/site.vm" ) );
103             IOUtil.copy( skinIS, jarOS );
104             jarOS.closeEntry();
105         }
106         finally
107         {
108             IOUtil.close( skinIS );
109             IOUtil.close( jarOS );
110         }
111 
112         oldLocale = Locale.getDefault();
113         Locale.setDefault( Locale.ENGLISH );
114     }
115 
116     private void copyVm( String filename, String append )
117         throws IOException
118     {
119         InputStream is = this.getResourceAsStream( "/org/apache/maven/doxia/siterenderer/resources/" + filename );
120         assertNotNull( is );
121         OutputStream os = new FileOutputStream( new File( getBasedir(), "target/test-classes/" + filename ) );
122         try
123         {
124             IOUtil.copy( is, os );
125             os.write( append.getBytes( "ISO-8859-1" ) );
126         }
127         finally
128         {
129             IOUtil.close( is );
130             IOUtil.close( os );
131         }
132     }
133 
134     /**
135      * @throws java.lang.Exception if something goes wrong.
136      * @see org.codehaus.plexus.PlexusTestCase#tearDown()
137      */
138     @Override
139     protected void tearDown()
140         throws Exception
141     {
142         release( renderer );
143         super.tearDown();
144 
145         Locale.setDefault( oldLocale );
146     }
147 
148     /**
149      * @throws Exception if something goes wrong.
150      */
151     public void testRender()
152         throws Exception
153     {
154         // Safety
155         FileUtils.deleteDirectory( getTestFile( OUTPUT ) );
156 
157         // ----------------------------------------------------------------------
158         // Render the site from src/test/resources/site to OUTPUT
159         // ----------------------------------------------------------------------
160         DecorationModel decoration = new DecorationXpp3Reader()
161             .read( new FileReader( getTestFile( "src/test/resources/site/site.xml" ) ) );
162 
163         SiteRenderingContext ctxt = getSiteRenderingContext( decoration, "src/test/resources/site", false );
164         renderer.render( renderer.locateDocumentFiles( ctxt ).values(), ctxt, getTestFile( OUTPUT ) );
165 
166         ctxt = getSiteRenderingContext( decoration, "src/test/resources/site-validate", true );
167         renderer.render( renderer.locateDocumentFiles( ctxt ).values(), ctxt, getTestFile( OUTPUT ) );
168 
169         // ----------------------------------------------------------------------
170         // Verify specific pages
171         // ----------------------------------------------------------------------
172         verifyHeadPage();
173         verifyCdcPage();
174         verifyNestedItemsPage();
175         verifyMultipleBlock();
176         verifyMacro();
177         verifyEntitiesPage();
178         verifyJavascriptPage();
179         verifyFaqPage();
180         verifyAttributes();
181         verifyMisc();
182         verifyDocbookPageExists();
183         verifyApt();
184         verifyExtensionInFilename();
185         verifyNewlines();
186 
187         // ----------------------------------------------------------------------
188         // Validate the rendering pages
189         // ----------------------------------------------------------------------
190         validatePages();
191     }
192 
193     public void testExternalReport()
194         throws Exception
195     {
196         DocumentRenderer docRenderer = mock( DocumentRenderer.class );
197         when( docRenderer.isExternalReport() ).thenReturn( true );
198         when( docRenderer.getOutputName() ).thenReturn( "external/index" );
199         when( docRenderer.getRenderingContext() ).thenReturn( new RenderingContext( new File( "" ), "index.html" )  );
200 
201         SiteRenderingContext context = new SiteRenderingContext();
202 
203         renderer.render( Collections.singletonList( docRenderer ), context, new File( "target/output" ) );
204 
205         verify( docRenderer ).renderDocument( isNull( Writer.class ), eq( renderer ), eq( context ) );
206     }
207 
208     public void testVelocityToolManager()
209         throws Exception
210     {
211         StringWriter writer = new StringWriter();
212 
213         SiteRenderingContext siteRenderingContext = new SiteRenderingContext();
214         siteRenderingContext.setDecoration( new DecorationModel() );
215 
216         Map<String, Object> attributes = new HashMap<String, Object>();
217 
218         /*
219          * We need to add doxiaSiteRendererVersion manually because version property from pom.properties
220          * is not available at test time in some cases.
221          */
222         attributes.put( "doxiaSiteRendererVersion", "1.7-bogus" );
223 
224         siteRenderingContext.setTemplateProperties( attributes );
225 
226         siteRenderingContext.setTemplateName( "org/apache/maven/doxia/siterenderer/velocity-toolmanager.vm" );
227         RenderingContext context = new RenderingContext( new File( "" ), "document.html" );
228         SiteRendererSink sink = new SiteRendererSink( context );
229         renderer.generateDocument( writer, sink, siteRenderingContext );
230 
231         String renderResult = writer.toString();
232         String expectedResult = IOUtils.toString( getClass().getResourceAsStream( "velocity-toolmanager.expected.txt" ) );
233         assertEquals( expectedResult, renderResult );
234     }
235 
236     public void testVelocityToolManagerForTemplate()
237         throws Exception
238     {
239         StringWriter writer = new StringWriter();
240 
241         File templateFile =
242             new File( getBasedir(), "target/test-classes/org/apache/maven/doxia/siterenderer/velocity-toolmanager.vm" );
243         Map<String, Object> attributes = new HashMap<String, Object>();
244 
245         /*
246          * We need to add doxiaSiteRendererVersion manually because version property from pom.properties
247          * is not available at test time in some cases.
248          */
249         attributes.put( "doxiaSiteRendererVersion", "1.7-bogus" );
250 
251         SiteRenderingContext siteRenderingContext =
252             renderer.createContextForTemplate( templateFile, attributes, new DecorationModel(),
253                                                "defaultWindowTitle", Locale.ENGLISH );
254         RenderingContext context = new RenderingContext( new File( "" ), "document.html" );
255         SiteRendererSink sink = new SiteRendererSink( context );
256         renderer.generateDocument( writer, sink, siteRenderingContext );
257 
258         String renderResult = writer.toString();
259         String expectedResult = IOUtils.toString( getClass().getResourceAsStream( "velocity-toolmanager.expected.txt" ) );
260         assertEquals( expectedResult, renderResult );
261     }
262 
263     public void testVelocityToolManagerForSkin()
264         throws Exception
265     {
266         StringWriter writer = new StringWriter();
267 
268         File skinFile = skinJar;
269 
270         Map<String, Object> attributes = new HashMap<String, Object>();
271 
272         /*
273          * We need to add doxiaSiteRendererVersion manually because version property from pom.properties
274          * is not available at test time in some cases.
275          */
276         attributes.put( "doxiaSiteRendererVersion", "1.7-bogus" );
277 
278         SiteRenderingContext siteRenderingContext =
279             renderer.createContextForSkin( skinFile, attributes, new DecorationModel(), "defaultWindowTitle",
280                                            Locale.ENGLISH );
281         RenderingContext context = new RenderingContext( new File( "" ), "document.html" );
282         SiteRendererSink sink = new SiteRendererSink( context );
283         renderer.generateDocument( writer, sink, siteRenderingContext );
284         String renderResult = writer.toString();
285         String expectedResult = IOUtils.toString( getClass().getResourceAsStream( "velocity-toolmanager.expected.txt" ) );
286         assertEquals( expectedResult, renderResult );
287     }
288 
289     public void testMatchVersion()
290         throws Exception
291     {
292         DefaultSiteRenderer r = (DefaultSiteRenderer) renderer;
293         assertTrue( r.matchVersion( "1.7", "1.7" ) );
294         assertFalse( r.matchVersion( "1.7", "1.8" ) );
295     }
296 
297     private SiteRenderingContext getSiteRenderingContext( DecorationModel decoration, String siteDir, boolean validate )
298     {
299         SiteRenderingContext ctxt = new SiteRenderingContext();
300         ctxt.setTemplateName( "default-site.vm" );
301         ctxt.setTemplateClassLoader( getClassLoader() );
302         ctxt.setUsingDefaultTemplate( true );
303         final Map<String, String> templateProp = new HashMap<String, String>();
304         templateProp.put( "outputEncoding", "UTF-8" );
305         ctxt.setTemplateProperties( templateProp );
306         ctxt.setDecoration( decoration );
307         ctxt.addSiteDirectory( getTestFile( siteDir ) );
308         ctxt.setValidate( validate );
309 
310         return ctxt;
311     }
312 
313     /**
314      * @throws Exception if something goes wrong.
315      */
316     public void verifyHeadPage()
317         throws Exception
318     {
319         new HeadVerifier().verify( "target/output/head.html" );
320     }
321 
322     /**
323      * @throws Exception if something goes wrong.
324      */
325     public void verifyCdcPage()
326         throws Exception
327     {
328         File nestedItems = getTestFile( "target/output/cdc.html" );
329         assertNotNull( nestedItems );
330         assertTrue( nestedItems.exists() );
331     }
332 
333     /**
334      * @throws Exception if something goes wrong.
335      */
336     public void verifyNestedItemsPage()
337         throws Exception
338     {
339         NestedItemsVerifier verifier = new NestedItemsVerifier();
340         verifier.verify( "target/output/nestedItems.html" );
341     }
342 
343     /**
344      * @throws Exception if something goes wrong.
345      */
346     public void verifyMultipleBlock()
347         throws Exception
348     {
349         MultipleBlockVerifier verifier = new MultipleBlockVerifier();
350         verifier.verify( "target/output/multipleblock.html" );
351     }
352 
353     /**
354      * @throws Exception if something goes wrong.
355      */
356     public void verifyMacro()
357         throws Exception
358     {
359         File macro = getTestFile( "target/output/macro.html" );
360         assertNotNull( macro );
361         assertTrue( macro.exists() );
362 
363         Reader reader = null;
364         try
365         {
366             reader = ReaderFactory.newXmlReader( macro );
367             String content = IOUtil.toString( reader );
368             assertEquals( content.indexOf( "</macro>" ), -1 );
369         }
370         finally
371         {
372             IOUtil.close( reader );
373         }
374     }
375 
376     /**
377      * @throws Exception if something goes wrong.
378      */
379     public void verifyEntitiesPage()
380         throws Exception
381     {
382         EntitiesVerifier verifier = new EntitiesVerifier();
383         verifier.verify( "target/output/entityTest.html" );
384     }
385 
386     /**
387      * @throws Exception if something goes wrong.
388      */
389     public void verifyJavascriptPage()
390         throws Exception
391     {
392         JavascriptVerifier verifier = new JavascriptVerifier();
393         verifier.verify( "target/output/javascript.html" );
394     }
395 
396     /**
397      * @throws Exception if something goes wrong.
398      */
399     public void verifyFaqPage()
400         throws Exception
401     {
402         FaqVerifier verifier = new FaqVerifier();
403         verifier.verify( "target/output/faq.html" );
404     }
405 
406     /**
407      * @throws Exception if something goes wrong.
408      */
409     public void verifyAttributes()
410         throws Exception
411     {
412         AttributesVerifier verifier = new AttributesVerifier();
413         verifier.verify( "target/output/attributes.html" );
414     }
415 
416     /**
417      * @throws Exception if something goes wrong.
418      */
419     public void verifyMisc()
420         throws Exception
421     {
422         AbstractVerifier verifier = new MiscVerifier();
423         verifier.verify( "target/output/misc.html" );
424 
425         verifier = new CommentsVerifier();
426         verifier.verify( "target/output/misc.html" );
427     }
428 
429     /**
430      * @throws Exception if something goes wrong.
431      */
432     public void verifyDocbookPageExists()
433         throws Exception
434     {
435         File output = getTestFile( "target/output/docbook.html" );
436         assertNotNull( output );
437         assertTrue( output.exists() );
438     }
439 
440     /**
441      * @throws Exception if something goes wrong.
442      */
443     public void verifyApt()
444         throws Exception
445     {
446         AbstractVerifier verifier = new AptVerifier();
447         verifier.verify( "target/output/apt.html" );
448 
449         verifier = new CommentsVerifier();
450         verifier.verify( "target/output/apt.html" );
451     }
452 
453     /**
454      * @throws Exception if something goes wrong.
455      */
456     public void verifyExtensionInFilename()
457         throws Exception
458     {
459         File output = getTestFile( "target/output/extension.apt.not.at.end.html" );
460         assertNotNull( output );
461         assertTrue( output.exists() );
462     }
463 
464     /**
465      * @throws Exception if something goes wrong.
466      */
467     public void verifyNewlines()
468         throws Exception
469     {
470         /* apt */
471         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/apt.html" ), "ISO-8859-1" ) );
472         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/cdc.html" ), "ISO-8859-1" ) );
473         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/interpolation.html" ), "ISO-8859-1" ) );
474         /* confluence */
475         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/confluence/anchor.html" ), "ISO-8859-1" ) );
476         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/confluence/code.html" ), "ISO-8859-1" ) );
477         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/confluence/table.html" ), "ISO-8859-1" ) );
478         /* docbook */
479         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/docbook.html" ), "ISO-8859-1" ) );
480         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/sdocbook_full.html" ), "ISO-8859-1" ) );
481         /* fml */
482         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/faq.html" ), "ISO-8859-1" ) );
483         /* xdoc */
484         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/attributes.html" ), "ISO-8859-1" ) );
485         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/javascript.html" ), "ISO-8859-1" ) );
486         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/head.html" ), "ISO-8859-1" ) );
487         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/macro.html" ), "ISO-8859-1" ) );
488     }
489 
490     private void checkNewlines( String content )
491     {
492         int cr = StringUtils.countMatches( content, "\r" );
493         int lf = StringUtils.countMatches( content, "\n" );
494         assertTrue( "Should contain only Windows or Unix newlines: cr = " + cr + ", lf = " + lf, ( cr == 0 )
495             || ( cr == lf ) );
496     }
497 
498     /**
499      * Validate the generated pages.
500      *
501      * @throws Exception if something goes wrong.
502      * @since 1.1.1
503      */
504     public void validatePages()
505         throws Exception
506     {
507         new XhtmlValidatorTest().validateGeneratedPages();
508     }
509 
510     protected static class XhtmlValidatorTest
511         extends AbstractXmlValidator
512     {
513         /**
514          * Validate the generated documents.
515          *
516          * @throws Exception
517          */
518         public void validateGeneratedPages()
519             throws Exception
520         {
521             setUp();
522             testValidateFiles();
523             tearDown();
524         }
525 
526         private static String[] getIncludes()
527         {
528             return new String[] { "**/*.html" };
529         }
530 
531         /** {@inheritDoc} */
532         protected String addNamespaces( String content )
533         {
534             return content;
535         }
536 
537         /** {@inheritDoc} */
538         protected EntityResolver getEntityResolver()
539         {
540             return new XhtmlEntityResolver();
541         }
542 
543         /** {@inheritDoc} */
544         protected Map<String,String> getTestDocuments()
545             throws IOException
546         {
547             Map<String,String> testDocs = new HashMap<String,String>();
548 
549             File dir = new File( getBasedir(), "target/output" );
550 
551             List<String> l =
552                 FileUtils.getFileNames( dir, getIncludes()[0], FileUtils.getDefaultExcludesAsString(), true );
553 
554             for ( String file : l )
555             {
556                 file = StringUtils.replace( file, "\\", "/" );
557 
558                 Reader reader = ReaderFactory.newXmlReader( new File( file ) );
559                 try
560                 {
561                     testDocs.put( file, IOUtil.toString( reader ) );
562                 }
563                 finally
564                 {
565                     IOUtil.close( reader );
566                 }
567             }
568 
569             return testDocs;
570         }
571 
572         /** {@inheritDoc} */
573         @Override
574         protected boolean isFailErrorMessage( String message )
575         {
576             return true;
577         }
578     }
579 }