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 1729055 2016-02-08 00:02:32Z 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
95          InputStream is =
96              this.getResourceAsStream( "/org/apache/maven/doxia/siterenderer/resources/default-site.vm" );
97          assertNotNull( is );
98          OutputStream os = new FileOutputStream( new File( getBasedir(), "target/test-classes/default-site.vm" ) );
99          try
100         {
101             IOUtil.copy( is, os );
102             os.write( "\n\n\n\r\n\r\n\r\n".getBytes( "ISO-8859-1" ) );
103         }
104         finally
105         {
106             IOUtil.close( is );
107             IOUtil.close( os );
108         }
109 
110         InputStream skinIS = this.getResourceAsStream( "velocity-toolmanager.vm" );
111         JarOutputStream jarOS = new JarOutputStream( new FileOutputStream( skinJar ) );
112         try
113         {
114             jarOS.putNextEntry( new ZipEntry( "META-INF/maven/site.vm" ) );
115             IOUtil.copy( skinIS, jarOS );
116             jarOS.closeEntry();
117         }
118         finally
119         {
120             IOUtil.close( skinIS );
121             IOUtil.close( jarOS );
122         }
123 
124         oldLocale = Locale.getDefault();
125         Locale.setDefault( Locale.ENGLISH );
126     }
127 
128     /**
129      * @throws java.lang.Exception if something goes wrong.
130      * @see org.codehaus.plexus.PlexusTestCase#tearDown()
131      */
132     @Override
133     protected void tearDown()
134         throws Exception
135     {
136         release( renderer );
137         super.tearDown();
138 
139         Locale.setDefault( oldLocale );
140     }
141 
142     /**
143      * @throws Exception if something goes wrong.
144      */
145     public void testRender()
146         throws Exception
147     {
148         // Safety
149         FileUtils.deleteDirectory( getTestFile( OUTPUT ) );
150 
151         // ----------------------------------------------------------------------
152         // Render the site from src/test/resources/site to OUTPUT
153         // ----------------------------------------------------------------------
154         DecorationModel decoration = new DecorationXpp3Reader()
155             .read( new FileReader( getTestFile( "src/test/resources/site/site.xml" ) ) );
156 
157         SiteRenderingContext ctxt = getSiteRenderingContext( decoration, "src/test/resources/site", false );
158         renderer.render( renderer.locateDocumentFiles( ctxt ).values(), ctxt, getTestFile( OUTPUT ) );
159 
160         ctxt = getSiteRenderingContext( decoration, "src/test/resources/site-validate", true );
161         renderer.render( renderer.locateDocumentFiles( ctxt ).values(), ctxt, getTestFile( OUTPUT ) );
162 
163         // ----------------------------------------------------------------------
164         // Verify specific pages
165         // ----------------------------------------------------------------------
166         verifyHeadPage();
167         verifyCdcPage();
168         verifyNestedItemsPage();
169         verifyMultipleBlock();
170         verifyMacro();
171         verifyEntitiesPage();
172         verifyJavascriptPage();
173         verifyFaqPage();
174         verifyAttributes();
175         verifyMisc();
176         verifyDocbookPageExists();
177         verifyApt();
178         verifyExtensionInFilename();
179         verifyNewlines();
180 
181         // ----------------------------------------------------------------------
182         // Validate the rendering pages
183         // ----------------------------------------------------------------------
184         validatePages();
185     }
186 
187     public void testExternalReport()
188         throws Exception
189     {
190         DocumentRenderer docRenderer = mock( DocumentRenderer.class );
191         when( docRenderer.isExternalReport() ).thenReturn( true );
192         when( docRenderer.getOutputName() ).thenReturn( "external/index" );
193         when( docRenderer.getRenderingContext() ).thenReturn( new RenderingContext( new File( "" ), "index.html" )  );
194 
195         SiteRenderingContext context = new SiteRenderingContext();
196 
197         renderer.render( Collections.singletonList( docRenderer ), context, new File( "target/output" ) );
198 
199         verify( docRenderer ).renderDocument( isNull( Writer.class ), eq( renderer ), eq( context ) );
200     }
201 
202     public void testVelocityToolManager()
203         throws Exception
204     {
205         StringWriter writer = new StringWriter();
206 
207         SiteRenderingContext siteRenderingContext = new SiteRenderingContext();
208         siteRenderingContext.setDecoration( new DecorationModel() );
209 
210         Map<String, Object> attributes = new HashMap<String, Object>();
211 
212         /*
213          * We need to add doxiaSiteRendererVersion manually because version property from pom.properties
214          * is not available at test time in some cases.
215          */
216         attributes.put( "doxiaSiteRendererVersion", "1.7-bogus" );
217 
218         siteRenderingContext.setTemplateProperties( attributes );
219 
220         siteRenderingContext.setTemplateName( "org/apache/maven/doxia/siterenderer/velocity-toolmanager.vm" );
221         RenderingContext context = new RenderingContext( new File( "" ), "document.html" );
222         SiteRendererSink sink = new SiteRendererSink( context );
223         renderer.generateDocument( writer, sink, siteRenderingContext );
224 
225         String renderResult = writer.toString();
226         String expectedResult = IOUtils.toString( getClass().getResourceAsStream( "velocity-toolmanager.expected.txt" ) );
227         assertEquals( expectedResult, renderResult );
228     }
229 
230     public void testVelocityToolManagerForTemplate()
231         throws Exception
232     {
233         StringWriter writer = new StringWriter();
234 
235         File templateFile =
236             new File( getBasedir(), "target/test-classes/org/apache/maven/doxia/siterenderer/velocity-toolmanager.vm" );
237         Map<String, Object> attributes = new HashMap<String, Object>();
238 
239         /*
240          * We need to add doxiaSiteRendererVersion manually because version property from pom.properties
241          * is not available at test time in some cases.
242          */
243         attributes.put( "doxiaSiteRendererVersion", "1.7-bogus" );
244 
245         SiteRenderingContext siteRenderingContext =
246             renderer.createContextForTemplate( templateFile, attributes, new DecorationModel(),
247                                                "defaultWindowTitle", Locale.ENGLISH );
248         RenderingContext context = new RenderingContext( new File( "" ), "document.html" );
249         SiteRendererSink sink = new SiteRendererSink( context );
250         renderer.generateDocument( writer, sink, siteRenderingContext );
251 
252         String renderResult = writer.toString();
253         String expectedResult = IOUtils.toString( getClass().getResourceAsStream( "velocity-toolmanager.expected.txt" ) );
254         assertEquals( expectedResult, renderResult );
255     }
256 
257     public void testVelocityToolManagerForSkin()
258         throws Exception
259     {
260         StringWriter writer = new StringWriter();
261 
262         File skinFile = skinJar;
263 
264         Map<String, Object> attributes = new HashMap<String, Object>();
265 
266         /*
267          * We need to add doxiaSiteRendererVersion manually because version property from pom.properties
268          * is not available at test time in some cases.
269          */
270         attributes.put( "doxiaSiteRendererVersion", "1.7-bogus" );
271 
272         SiteRenderingContext siteRenderingContext =
273             renderer.createContextForSkin( skinFile, attributes, new DecorationModel(), "defaultWindowTitle",
274                                            Locale.ENGLISH );
275         RenderingContext context = new RenderingContext( new File( "" ), "document.html" );
276         SiteRendererSink sink = new SiteRendererSink( context );
277         renderer.generateDocument( writer, sink, siteRenderingContext );
278         String renderResult = writer.toString();
279         String expectedResult = IOUtils.toString( getClass().getResourceAsStream( "velocity-toolmanager.expected.txt" ) );
280         assertEquals( expectedResult, renderResult );
281     }
282 
283     public void testMatchVersion()
284         throws Exception
285     {
286         DefaultSiteRenderer r = (DefaultSiteRenderer) renderer;
287         assertTrue( r.matchVersion( "1.7", "1.7" ) );
288         assertFalse( r.matchVersion( "1.7", "1.8" ) );
289     }
290 
291     private SiteRenderingContext getSiteRenderingContext( DecorationModel decoration, String siteDir, boolean validate )
292     {
293         SiteRenderingContext ctxt = new SiteRenderingContext();
294         ctxt.setTemplateName( "default-site.vm" );
295         ctxt.setTemplateClassLoader( getClassLoader() );
296         ctxt.setUsingDefaultTemplate( true );
297         final Map<String, String> templateProp = new HashMap<String, String>();
298         templateProp.put( "outputEncoding", "UTF-8" );
299         ctxt.setTemplateProperties( templateProp );
300         ctxt.setDecoration( decoration );
301         ctxt.addSiteDirectory( getTestFile( siteDir ) );
302         ctxt.setValidate( validate );
303 
304         return ctxt;
305     }
306 
307     /**
308      * @throws Exception if something goes wrong.
309      */
310     public void verifyHeadPage()
311         throws Exception
312     {
313         new HeadVerifier().verify( "target/output/head.html" );
314     }
315 
316     /**
317      * @throws Exception if something goes wrong.
318      */
319     public void verifyCdcPage()
320         throws Exception
321     {
322         File nestedItems = getTestFile( "target/output/cdc.html" );
323         assertNotNull( nestedItems );
324         assertTrue( nestedItems.exists() );
325     }
326 
327     /**
328      * @throws Exception if something goes wrong.
329      */
330     public void verifyNestedItemsPage()
331         throws Exception
332     {
333         NestedItemsVerifier verifier = new NestedItemsVerifier();
334         verifier.verify( "target/output/nestedItems.html" );
335     }
336 
337     /**
338      * @throws Exception if something goes wrong.
339      */
340     public void verifyMultipleBlock()
341         throws Exception
342     {
343         MultipleBlockVerifier verifier = new MultipleBlockVerifier();
344         verifier.verify( "target/output/multipleblock.html" );
345     }
346 
347     /**
348      * @throws Exception if something goes wrong.
349      */
350     public void verifyMacro()
351         throws Exception
352     {
353         File macro = getTestFile( "target/output/macro.html" );
354         assertNotNull( macro );
355         assertTrue( macro.exists() );
356 
357         Reader reader = null;
358         try
359         {
360             reader = ReaderFactory.newXmlReader( macro );
361             String content = IOUtil.toString( reader );
362             assertEquals( content.indexOf( "</macro>" ), -1 );
363         }
364         finally
365         {
366             IOUtil.close( reader );
367         }
368     }
369 
370     /**
371      * @throws Exception if something goes wrong.
372      */
373     public void verifyEntitiesPage()
374         throws Exception
375     {
376         EntitiesVerifier verifier = new EntitiesVerifier();
377         verifier.verify( "target/output/entityTest.html" );
378     }
379 
380     /**
381      * @throws Exception if something goes wrong.
382      */
383     public void verifyJavascriptPage()
384         throws Exception
385     {
386         JavascriptVerifier verifier = new JavascriptVerifier();
387         verifier.verify( "target/output/javascript.html" );
388     }
389 
390     /**
391      * @throws Exception if something goes wrong.
392      */
393     public void verifyFaqPage()
394         throws Exception
395     {
396         FaqVerifier verifier = new FaqVerifier();
397         verifier.verify( "target/output/faq.html" );
398     }
399 
400     /**
401      * @throws Exception if something goes wrong.
402      */
403     public void verifyAttributes()
404         throws Exception
405     {
406         AttributesVerifier verifier = new AttributesVerifier();
407         verifier.verify( "target/output/attributes.html" );
408     }
409 
410     /**
411      * @throws Exception if something goes wrong.
412      */
413     public void verifyMisc()
414         throws Exception
415     {
416         AbstractVerifier verifier = new MiscVerifier();
417         verifier.verify( "target/output/misc.html" );
418 
419         verifier = new CommentsVerifier();
420         verifier.verify( "target/output/misc.html" );
421     }
422 
423     /**
424      * @throws Exception if something goes wrong.
425      */
426     public void verifyDocbookPageExists()
427         throws Exception
428     {
429         File output = getTestFile( "target/output/docbook.html" );
430         assertNotNull( output );
431         assertTrue( output.exists() );
432     }
433 
434     /**
435      * @throws Exception if something goes wrong.
436      */
437     public void verifyApt()
438         throws Exception
439     {
440         AbstractVerifier verifier = new AptVerifier();
441         verifier.verify( "target/output/apt.html" );
442 
443         verifier = new CommentsVerifier();
444         verifier.verify( "target/output/apt.html" );
445     }
446 
447     /**
448      * @throws Exception if something goes wrong.
449      */
450     public void verifyExtensionInFilename()
451         throws Exception
452     {
453         File output = getTestFile( "target/output/extension.apt.not.at.end.html" );
454         assertNotNull( output );
455         assertTrue( output.exists() );
456     }
457 
458     /**
459      * @throws Exception if something goes wrong.
460      */
461     public void verifyNewlines()
462         throws Exception
463     {
464         /* apt */
465         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/apt.html" ), "ISO-8859-1" ) );
466         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/cdc.html" ), "ISO-8859-1" ) );
467         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/interpolation.html" ), "ISO-8859-1" ) );
468         /* confluence */
469         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/confluence/anchor.html" ), "ISO-8859-1" ) );
470         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/confluence/code.html" ), "ISO-8859-1" ) );
471         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/confluence/table.html" ), "ISO-8859-1" ) );
472         /* docbook */
473         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/docbook.html" ), "ISO-8859-1" ) );
474         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/sdocbook_full.html" ), "ISO-8859-1" ) );
475         /* fml */
476         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/faq.html" ), "ISO-8859-1" ) );
477         /* xdoc */
478         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/attributes.html" ), "ISO-8859-1" ) );
479         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/javascript.html" ), "ISO-8859-1" ) );
480         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/head.html" ), "ISO-8859-1" ) );
481         checkNewlines( FileUtils.fileRead( getTestFile( "target/output/macro.html" ), "ISO-8859-1" ) );
482     }
483 
484     private void checkNewlines( String content )
485     {
486         int cr = StringUtils.countMatches( content, "\r" );
487         int lf = StringUtils.countMatches( content, "\n" );
488         assertTrue( "Should contain only Windows or Unix newlines: cr = " + cr + ", lf = " + lf, ( cr == 0 )
489             || ( cr == lf ) );
490     }
491 
492     /**
493      * Validate the generated pages.
494      *
495      * @throws Exception if something goes wrong.
496      * @since 1.1.1
497      */
498     public void validatePages()
499         throws Exception
500     {
501         new XhtmlValidatorTest().validateGeneratedPages();
502     }
503 
504     protected static class XhtmlValidatorTest
505         extends AbstractXmlValidator
506     {
507         /**
508          * Validate the generated documents.
509          *
510          * @throws Exception
511          */
512         public void validateGeneratedPages()
513             throws Exception
514         {
515             setUp();
516             testValidateFiles();
517             tearDown();
518         }
519 
520         private static String[] getIncludes()
521         {
522             return new String[] { "**/*.html" };
523         }
524 
525         /** {@inheritDoc} */
526         protected String addNamespaces( String content )
527         {
528             return content;
529         }
530 
531         /** {@inheritDoc} */
532         protected EntityResolver getEntityResolver()
533         {
534             return new XhtmlEntityResolver();
535         }
536 
537         /** {@inheritDoc} */
538         protected Map<String,String> getTestDocuments()
539             throws IOException
540         {
541             Map<String,String> testDocs = new HashMap<String,String>();
542 
543             File dir = new File( getBasedir(), "target/output" );
544 
545             List<String> l =
546                 FileUtils.getFileNames( dir, getIncludes()[0], FileUtils.getDefaultExcludesAsString(), true );
547 
548             for ( String file : l )
549             {
550                 file = StringUtils.replace( file, "\\", "/" );
551 
552                 Reader reader = ReaderFactory.newXmlReader( new File( file ) );
553                 try
554                 {
555                     testDocs.put( file, IOUtil.toString( reader ) );
556                 }
557                 finally
558                 {
559                     IOUtil.close( reader );
560                 }
561             }
562 
563             return testDocs;
564         }
565 
566         /** {@inheritDoc} */
567         @Override
568         protected boolean isFailErrorMessage( String message )
569         {
570             return true;
571         }
572     }
573 }