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 4613 2012-09-22 10:07:08Z schulte $
029 *
030 */
031package org.jomc.ant.test;
032
033import java.io.File;
034import java.io.IOException;
035import java.net.URL;
036import java.util.ArrayList;
037import java.util.Collection;
038import java.util.Locale;
039import java.util.Properties;
040import javax.xml.bind.JAXBException;
041import javax.xml.bind.Marshaller;
042import org.apache.commons.io.FileUtils;
043import org.apache.commons.lang.builder.ToStringBuilder;
044import org.apache.tools.ant.BuildEvent;
045import org.apache.tools.ant.BuildException;
046import org.apache.tools.ant.Project;
047import org.apache.tools.ant.ProjectHelper;
048import org.jomc.ant.JomcTask;
049import org.jomc.ant.test.support.AntExecutionRequest;
050import org.jomc.ant.test.support.AntExecutionResult;
051import org.jomc.ant.test.support.AntExecutor;
052import org.jomc.ant.test.support.DefaultAntExecutor;
053import org.jomc.ant.types.KeyValueType;
054import org.jomc.ant.types.NameType;
055import org.jomc.ant.types.PropertiesResourceType;
056import org.jomc.ant.types.TransformerResourceType;
057import org.jomc.model.ModelObject;
058import org.jomc.modlet.ModelContext;
059import org.jomc.modlet.ModelContextFactory;
060import org.jomc.modlet.ModelException;
061import org.jomc.modlet.Modlet;
062import org.jomc.modlet.ModletObject;
063import org.jomc.modlet.Modlets;
064import org.jomc.modlet.ObjectFactory;
065import static org.jomc.ant.test.support.Assert.assertException;
066import static org.jomc.ant.test.support.Assert.assertExceptionMessage;
067import static org.jomc.ant.test.support.Assert.assertMessageLogged;
068import static org.jomc.ant.test.support.Assert.assertMessageNotLogged;
069import static org.jomc.ant.test.support.Assert.assertNoException;
070import org.junit.After;
071import org.junit.Before;
072import org.junit.Test;
073import static org.junit.Assert.assertFalse;
074import static org.junit.Assert.assertNotNull;
075import static org.junit.Assert.assertNull;
076import static org.junit.Assert.assertTrue;
077import static org.junit.Assert.fail;
078
079/**
080 * Test cases for class {@code org.jomc.ant.JomcTask}.
081 *
082 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
083 * @version $JOMC: JomcTaskTest.java 4613 2012-09-22 10:07:08Z schulte $
084 */
085public 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}