001    /*
002     *   Copyright (C) Christian Schulte, 2005-206
003     *   All rights reserved.
004     *
005     *   Redistribution and use in source and binary forms, with or without
006     *   modification, are permitted provided that the following conditions
007     *   are met:
008     *
009     *     o Redistributions of source code must retain the above copyright
010     *       notice, this list of conditions and the following disclaimer.
011     *
012     *     o Redistributions in binary form must reproduce the above copyright
013     *       notice, this list of conditions and the following disclaimer in
014     *       the documentation and/or other materials provided with the
015     *       distribution.
016     *
017     *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
018     *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
019     *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
020     *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
021     *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
022     *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
023     *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
024     *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025     *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
026     *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027     *
028     *   $JOMC: JomcTaskTest.java 4200 2012-01-25 09:46:13Z schulte2005 $
029     *
030     */
031    package org.jomc.ant.test;
032    
033    import java.io.File;
034    import java.io.IOException;
035    import java.net.URL;
036    import java.util.ArrayList;
037    import java.util.Collection;
038    import java.util.Locale;
039    import java.util.Properties;
040    import javax.xml.bind.JAXBException;
041    import javax.xml.bind.Marshaller;
042    import org.apache.commons.io.FileUtils;
043    import org.apache.commons.lang.builder.ToStringBuilder;
044    import org.apache.tools.ant.BuildEvent;
045    import org.apache.tools.ant.BuildException;
046    import org.apache.tools.ant.Project;
047    import org.apache.tools.ant.ProjectHelper;
048    import org.jomc.ant.JomcTask;
049    import org.jomc.ant.test.support.AntExecutionRequest;
050    import org.jomc.ant.test.support.AntExecutionResult;
051    import org.jomc.ant.test.support.AntExecutor;
052    import org.jomc.ant.test.support.DefaultAntExecutor;
053    import org.jomc.ant.types.KeyValueType;
054    import org.jomc.ant.types.NameType;
055    import org.jomc.ant.types.PropertiesResourceType;
056    import org.jomc.ant.types.TransformerResourceType;
057    import org.jomc.model.ModelObject;
058    import org.jomc.modlet.ModelContext;
059    import org.jomc.modlet.ModelContextFactory;
060    import org.jomc.modlet.ModelException;
061    import org.jomc.modlet.Modlet;
062    import org.jomc.modlet.ModletObject;
063    import org.jomc.modlet.Modlets;
064    import org.jomc.modlet.ObjectFactory;
065    import static org.jomc.ant.test.support.Assert.assertException;
066    import static org.jomc.ant.test.support.Assert.assertExceptionMessage;
067    import static org.jomc.ant.test.support.Assert.assertMessageLogged;
068    import static org.jomc.ant.test.support.Assert.assertMessageNotLogged;
069    import static org.jomc.ant.test.support.Assert.assertNoException;
070    import org.junit.After;
071    import org.junit.Before;
072    import org.junit.Test;
073    import static org.junit.Assert.assertFalse;
074    import static org.junit.Assert.assertNotNull;
075    import static org.junit.Assert.assertNull;
076    import static org.junit.Assert.assertTrue;
077    import static org.junit.Assert.fail;
078    
079    /**
080     * Test cases for class {@code org.jomc.ant.JomcTask}.
081     *
082     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
083     * @version $JOMC: JomcTaskTest.java 4200 2012-01-25 09:46:13Z schulte2005 $
084     */
085    public class JomcTaskTest
086    {
087    
088        /** Constant to prefix relative resource names with. */
089        private static final String ABSOLUTE_RESOURCE_NAME_PREFIX = "/org/jomc/ant/test/";
090    
091        /** Cached default locale. */
092        private static final Locale DEFAULT_LOCALE = Locale.getDefault();
093    
094        /** Constant for the name of the system property holding the output directory for the test. */
095        private static final String OUTPUT_DIRECTORY_PROPERTY_NAME = "jomc.test.outputDirectory";
096    
097        /** The {@code JomcTask} instance tests are performed with. */
098        private JomcTask jomcTask;
099    
100        /** The {@code Project} backing the test. */
101        private Project project;
102    
103        /** The {@code AntExecutor} backing the test. */
104        private AntExecutor antExecutor;
105    
106        /** The output directory of the instance. */
107        private File outputDirectory;
108    
109        /** Creates a new {@code JomcTaskTest} instance. */
110        public JomcTaskTest()
111        {
112            super();
113        }
114    
115        /**
116         * Gets the output directory of instance.
117         *
118         * @return The output directory of instance.
119         */
120        public final File getOutputDirectory()
121        {
122            if ( this.outputDirectory == null )
123            {
124                final String name = System.getProperty( OUTPUT_DIRECTORY_PROPERTY_NAME );
125                assertNotNull( "Expected '" + OUTPUT_DIRECTORY_PROPERTY_NAME + "' system property not found.", name );
126                this.outputDirectory = new File( new File( name ), this.getClass().getSimpleName() );
127                assertTrue( "Expected '" + OUTPUT_DIRECTORY_PROPERTY_NAME + "' system property to hold an absolute path.",
128                            this.outputDirectory.isAbsolute() );
129    
130                if ( !this.outputDirectory.exists() )
131                {
132                    assertTrue( this.outputDirectory.mkdirs() );
133                }
134            }
135    
136            return this.outputDirectory;
137        }
138    
139        /**
140         * Gets the {@code JomcTask} instance tests are performed with.
141         *
142         * @return The {@code JomcTask} instance tests are performed with.
143         *
144         * @see #newJomcTask()
145         */
146        public JomcTask getJomcTask()
147        {
148            if ( this.jomcTask == null )
149            {
150                this.jomcTask = this.newJomcTask();
151                this.jomcTask.setProject( this.getProject() );
152            }
153    
154            return this.jomcTask;
155        }
156    
157        /**
158         * Creates a new {@code JomcTask} instance to test.
159         *
160         * @return A new {@code JomcTask} instance to test.
161         *
162         * @see #getJomcTask()
163         */
164        protected JomcTask newJomcTask()
165        {
166            return new JomcTask();
167        }
168    
169        /**
170         * Gets the {@code Project} backing the test.
171         *
172         * @return The {@code Project} backing the test.
173         *
174         * @see #newProject()
175         */
176        public Project getProject()
177        {
178            if ( this.project == null )
179            {
180                this.project = this.newProject();
181            }
182    
183            return this.project;
184        }
185    
186        /**
187         * Creates and configures a new {@code Project} instance backing the test.
188         *
189         * @return A new {@code Project} instance backing the test.
190         *
191         * @see #getProject()
192         * @see #getBuildFileName()
193         */
194        protected Project newProject()
195        {
196            try
197            {
198                final Project p = new Project();
199                p.init();
200    
201                final URL buildFileResource =
202                    this.getClass().getResource( ABSOLUTE_RESOURCE_NAME_PREFIX + this.getBuildFileName() );
203    
204                assertNotNull( "Expected '" + this.getBuildFileName() + "' resource not found.", buildFileResource );
205                final File buildFile = new File( this.getOutputDirectory(), this.getBuildFileName() );
206                assertTrue( buildFile.isAbsolute() );
207                FileUtils.copyURLToFile( buildFileResource, buildFile );
208    
209                final URL classfilesResource =
210                    this.getClass().getResource( ABSOLUTE_RESOURCE_NAME_PREFIX + "classfiles.zip" );
211    
212                assertNotNull( "Expected 'classfiles.zip' resource not found.", classfilesResource );
213                final File classfilesZip = new File( this.getOutputDirectory(), "classfiles.zip" );
214                assertTrue( classfilesZip.isAbsolute() );
215                FileUtils.copyURLToFile( classfilesResource, classfilesZip );
216    
217                final File classpathDirectory = new File( new File( this.getOutputDirectory(), "redundant" ), "META-INF" );
218                assertTrue( classpathDirectory.isAbsolute() );
219    
220                if ( !classpathDirectory.exists() )
221                {
222                    assertTrue( classpathDirectory.mkdirs() );
223                }
224    
225                final ModelContext modelContext = ModelContextFactory.newInstance().newModelContext();
226                final Modlets modlets = modelContext.getModlets();
227                final Modlet redundantModlet =
228                    modlets.getMergedModlet( "JOMC Ant Tasks Tests", ModelObject.MODEL_PUBLIC_ID );
229    
230                final Marshaller marshaller = modelContext.createMarshaller( ModletObject.MODEL_PUBLIC_ID );
231                marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
232                marshaller.marshal( new ObjectFactory().createModlet( redundantModlet ),
233                                    new File( classpathDirectory, "jomc-modlet.xml" ) );
234    
235                final File servicesDir = new File( classpathDirectory, "services" );
236                assertTrue( servicesDir.isAbsolute() );
237    
238                if ( !servicesDir.exists() )
239                {
240                    assertTrue( servicesDir.mkdirs() );
241                }
242    
243                final File modletProviderService = new File( servicesDir, "org.jomc.modlet.ModletProvider" );
244                FileUtils.writeStringToFile( modletProviderService, "org.jomc.modlet.DefaultModletProvider\n", "UTF-8" );
245    
246                p.setProperty( "basedir", buildFile.getParentFile().getAbsolutePath() );
247                p.setUserProperty( "ant.file", buildFile.getAbsolutePath() );
248                p.setUserProperty( "output.dir", this.getOutputDirectory().getAbsolutePath() );
249                p.setUserProperty( "test.output.dir", new File( this.getOutputDirectory(), "work" ).getAbsolutePath() );
250                p.setUserProperty( "test.classpath.dir", classpathDirectory.getParentFile().getAbsolutePath() );
251                ProjectHelper.configureProject( p, buildFile );
252                return p;
253            }
254            catch ( final IOException e )
255            {
256                throw new AssertionError( e );
257            }
258            catch ( final ModelException e )
259            {
260                throw new AssertionError( e );
261            }
262            catch ( final JAXBException e )
263            {
264                throw new AssertionError( e );
265            }
266            catch ( final BuildException e )
267            {
268                throw new AssertionError( e );
269            }
270        }
271    
272        /**
273         * Gets the {@code AntExecutor} instance backing the test.
274         *
275         * @return The {@code AntExecutor} instance backing the test.
276         *
277         * @see #newAntExecutor()
278         */
279        public AntExecutor getAntExecutor()
280        {
281            if ( this.antExecutor == null )
282            {
283                this.antExecutor = this.newAntExecutor();
284            }
285    
286            return this.antExecutor;
287        }
288    
289        /**
290         * Creates a new {@code AntExecutor} instance backing the test.
291         *
292         * @return A new {@code AntExecutor} instance backing the test.
293         *
294         * @see #getAntExecutor()
295         */
296        protected AntExecutor newAntExecutor()
297        {
298            return new DefaultAntExecutor();
299        }
300    
301        /**
302         * Gets the name of the build file backing the test.
303         *
304         * @return The the name of the build file backing the test.
305         *
306         * @see #newProject()
307         */
308        protected String getBuildFileName()
309        {
310            return "jomc-task-test.xml";
311        }
312    
313        @Before
314        public void setUp() throws Exception
315        {
316            Locale.setDefault( Locale.ENGLISH );
317    
318            if ( this.getProject().getTargets().containsKey( "before-test" ) )
319            {
320                assertNoException( this.executeTarget( "before-test" ) );
321            }
322        }
323    
324        @After
325        public void tearDown() throws Exception
326        {
327            Locale.setDefault( DEFAULT_LOCALE );
328    
329            if ( this.getProject().getTargets().containsKey( "after-test" ) )
330            {
331                assertNoException( this.executeTarget( "after-test" ) );
332            }
333        }
334    
335        /**
336         * Executes an Ant target.
337         *
338         * @param target The name of the target to execute.
339         *
340         * @return The result of the execution.
341         *
342         * @throws NullPointerException if {@code target} is {@code null}.
343         */
344        public AntExecutionResult executeTarget( final String target )
345        {
346            if ( target == null )
347            {
348                throw new NullPointerException( "target" );
349            }
350    
351            final AntExecutionResult r =
352                this.getAntExecutor().executeAnt( new AntExecutionRequest( this.getProject(), target ) );
353    
354            System.out.println( "======================================================================" );
355            System.out.println( "Target: " + target );
356            System.out.println( "======================================================================" );
357            System.out.println( "System output:" );
358            System.out.println( r.getSystemOutput() );
359            System.out.println();
360            System.out.println( "======================================================================" );
361            System.out.println( "System error:" );
362            System.out.println( r.getSystemError() );
363            System.out.println();
364    
365            if ( r.getThrowable() != null )
366            {
367                System.out.println( "======================================================================" );
368                System.out.println( "Exception:" );
369                r.getThrowable().printStackTrace();
370                System.out.println();
371            }
372    
373            System.out.println( "======================================================================" );
374            System.out.println( "Log:" );
375    
376            for ( BuildEvent e : r.getMessageLoggedEvents() )
377            {
378                System.out.println( ToStringBuilder.reflectionToString( e ) );
379            }
380    
381            System.out.println();
382            System.out.println();
383    
384            return r;
385        }
386    
387        @Test
388        public final void testAssertNotNull() throws Exception
389        {
390            try
391            {
392                this.getJomcTask().assertNotNull( null, null );
393                fail( "Expected 'NullPointerException' not thrown." );
394            }
395            catch ( final NullPointerException e )
396            {
397                assertNotNull( e.getMessage() );
398                System.out.println( e );
399            }
400    
401            try
402            {
403                this.getJomcTask().assertNotNull( "TEST", null );
404                fail( "Expected 'BuildException' not thrown." );
405            }
406            catch ( final BuildException e )
407            {
408                assertNotNull( e.getMessage() );
409                System.out.println( e );
410            }
411        }
412    
413        @Test
414        public final void testAssertNamesNotNull() throws Exception
415        {
416            try
417            {
418                this.getJomcTask().assertNamesNotNull( null );
419                fail( "Expected 'NullPointerException' not thrown." );
420            }
421            catch ( final NullPointerException e )
422            {
423                assertNotNull( e.getMessage() );
424                System.out.println( e );
425            }
426    
427            final Collection<NameType> names = new ArrayList<NameType>( 1 );
428            names.add( new NameType() );
429    
430            try
431            {
432                this.getJomcTask().assertNamesNotNull( names );
433                fail( "Expected 'BuildException' not thrown." );
434            }
435            catch ( final BuildException e )
436            {
437                assertNotNull( e.getMessage() );
438                System.out.println( e );
439            }
440        }
441    
442        @Test
443        public final void testAssertKeysNotNull() throws Exception
444        {
445            try
446            {
447                this.getJomcTask().assertKeysNotNull( null );
448                fail( "Expected 'NullPointerException' not thrown." );
449            }
450            catch ( final NullPointerException e )
451            {
452                assertNotNull( e.getMessage() );
453                System.out.println( e );
454            }
455    
456            final Collection<KeyValueType> keys = new ArrayList<KeyValueType>( 1 );
457            keys.add( new KeyValueType() );
458    
459            try
460            {
461                this.getJomcTask().assertKeysNotNull( keys );
462                fail( "Expected 'BuildException' not thrown." );
463            }
464            catch ( final BuildException e )
465            {
466                assertNotNull( e.getMessage() );
467                System.out.println( e );
468            }
469        }
470    
471        @Test
472        public final void testAssertLocationsNotNull() throws Exception
473        {
474            try
475            {
476                this.getJomcTask().assertLocationsNotNull( null );
477                fail( "Expected 'NullPointerException' not thrown." );
478            }
479            catch ( final NullPointerException e )
480            {
481                assertNotNull( e.getMessage() );
482                System.out.println( e );
483            }
484    
485            final Collection<PropertiesResourceType> locations = new ArrayList<PropertiesResourceType>( 1 );
486            locations.add( new PropertiesResourceType() );
487    
488            try
489            {
490                this.getJomcTask().assertLocationsNotNull( locations );
491                fail( "Expected 'BuildException' not thrown." );
492            }
493            catch ( final BuildException e )
494            {
495                assertNotNull( e.getMessage() );
496                System.out.println( e );
497            }
498        }
499    
500        @Test
501        public final void testGetTransformer() throws Exception
502        {
503            try
504            {
505                this.getJomcTask().getTransformer( null );
506                fail( "Expected 'NullPointerException' not thrown." );
507            }
508            catch ( final NullPointerException e )
509            {
510                assertNotNull( e.getMessage() );
511                System.out.println( e );
512            }
513    
514            final TransformerResourceType r = new TransformerResourceType();
515            r.setLocation( "DOES_NOT_EXIST" );
516            r.setOptional( true );
517            assertNull( this.getJomcTask().getTransformer( r ) );
518        }
519    
520        @Test
521        public final void testGetResource() throws Exception
522        {
523            try
524            {
525                this.getJomcTask().getResource( null );
526                fail( "Expected 'NullPointerException' not thrown." );
527            }
528            catch ( final NullPointerException e )
529            {
530                assertNotNull( e.getMessage() );
531                System.out.println( e );
532            }
533    
534            assertNull( this.getJomcTask().getResource( "DOES_NOT_EXIST" ) );
535            assertNotNull( this.getJomcTask().getResource( "file://DOES_NOT_EXIST" ) );
536        }
537    
538        @Test
539        public final void testGetProperties() throws Exception
540        {
541            try
542            {
543                this.getJomcTask().getProperties( null );
544                fail( "Expected 'NullPointerException' not thrown." );
545            }
546            catch ( final NullPointerException e )
547            {
548                assertNotNull( e.getMessage() );
549                System.out.println( e );
550            }
551    
552            final PropertiesResourceType r = new PropertiesResourceType();
553            r.setLocation( "DOES_NOT_EXIST" );
554            r.setOptional( true );
555    
556            final Properties p = this.getJomcTask().getProperties( r );
557            assertNotNull( p );
558            assertTrue( p.isEmpty() );
559        }
560    
561        @Test
562        public final void testGetModel() throws Exception
563        {
564            try
565            {
566                this.getJomcTask().getModel( null );
567                fail( "Expected 'NullPointerException' not thrown." );
568            }
569            catch ( final NullPointerException e )
570            {
571                assertNotNull( e.getMessage() );
572                System.out.println( e );
573            }
574        }
575    
576        @Test
577        public final void testExecuteTask() throws Exception
578        {
579            final AntExecutionResult r = this.executeTarget( "test-execute-task" );
580            assertNoException( r );
581            assertMessageLogged( r, "--------------------------------------------------------------------------------" );
582        }
583    
584        @Test
585        public final void testExecuteTaskIf() throws Exception
586        {
587            final AntExecutionResult r = this.executeTarget( "test-execute-task-if" );
588            assertNoException( r );
589            assertMessageLogged( r, "--------------------------------------------------------------------------------" );
590        }
591    
592        @Test
593        public final void testExecuteTaskUnless() throws Exception
594        {
595            final AntExecutionResult r = this.executeTarget( "test-execute-task-unless" );
596            assertNoException( r );
597            assertMessageNotLogged( r, "--------------------------------------------------------------------------------" );
598        }
599    
600        @Test
601        public final void testCloneable() throws Exception
602        {
603            assertTrue( this.getJomcTask() == this.getJomcTask() );
604            assertFalse( this.getJomcTask() == this.getJomcTask().clone() );
605        }
606    
607        @Test
608        public final void testModelContextAttributeMissingKey() throws Exception
609        {
610            final AntExecutionResult r = this.executeTarget( "test-model-context-attribute-missing-key" );
611            assertException( r, BuildException.class );
612            assertExceptionMessage( r, "Mandatory attribute 'key' is missing a value." );
613        }
614    
615        @Test
616        public final void testTransformationParameterMissingKey() throws Exception
617        {
618            final AntExecutionResult r = this.executeTarget( "test-transformation-parameter-missing-key" );
619            assertException( r, BuildException.class );
620            assertExceptionMessage( r, "Mandatory attribute 'key' is missing a value." );
621        }
622    
623        @Test
624        public final void testTransformationParameterResourceMissingLocation() throws Exception
625        {
626            final AntExecutionResult r = this.executeTarget( "test-transformation-parameter-resource-missing-location" );
627            assertException( r, BuildException.class );
628            assertExceptionMessage( r, "Mandatory attribute 'location' is missing a value." );
629        }
630    
631        @Test
632        public final void testTransformationOutputPropertyMissingKey() throws Exception
633        {
634            final AntExecutionResult r = this.executeTarget( "test-transformation-output-property-missing-key" );
635            assertException( r, BuildException.class );
636            assertExceptionMessage( r, "Mandatory attribute 'key' is missing a value." );
637        }
638    
639    }