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: DefaultModelValidatorTest.java 4200 2012-01-25 09:46:13Z schulte2005 $
029     *
030     */
031    package org.jomc.model.modlet.test;
032    
033    import java.util.List;
034    import java.util.logging.Level;
035    import javax.xml.bind.JAXBContext;
036    import javax.xml.bind.JAXBElement;
037    import javax.xml.bind.JAXBException;
038    import javax.xml.bind.util.JAXBSource;
039    import org.jomc.model.ModelObject;
040    import org.jomc.model.Modules;
041    import org.jomc.model.modlet.DefaultModelValidator;
042    import org.jomc.model.modlet.ModelHelper;
043    import org.jomc.model.test.ModelValidationReportDetail;
044    import org.jomc.model.test.ModulesConstraintsTestType;
045    import org.jomc.model.test.SchemaConstraintsTestType;
046    import org.jomc.model.test.TestSuite;
047    import org.jomc.modlet.Model;
048    import org.jomc.modlet.ModelContext;
049    import org.jomc.modlet.ModelContextFactory;
050    import org.jomc.modlet.ModelException;
051    import org.jomc.modlet.ModelValidationReport;
052    import org.junit.Test;
053    import static org.junit.Assert.assertEquals;
054    import static org.junit.Assert.assertNotNull;
055    import static org.junit.Assert.assertTrue;
056    import static org.junit.Assert.fail;
057    
058    /**
059     * Test cases for class {@code org.jomc.model.modlet.DefaultModelValidator} implementations.
060     *
061     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a> 1.0
062     * @version $JOMC: DefaultModelValidatorTest.java 4200 2012-01-25 09:46:13Z schulte2005 $
063     */
064    public class DefaultModelValidatorTest
065    {
066    
067        /** Constant to prefix relative resource names with. */
068        private static final String ABSOLUTE_RESOURCE_NAME_PREFIX = "/org/jomc/model/modlet/test/";
069    
070        /** The {@code DefaultModelValidator} instance tests are performed with. */
071        private DefaultModelValidator defaultModelValidator;
072    
073        /** The {@code TestSuite} holding module tests to run. */
074        private TestSuite testSuite;
075    
076        /** The {@code ModelContext} tests are performed with. */
077        private ModelContext modelContext;
078    
079        /** Creates a new {@code DefaultModelValidatorTest} instance. */
080        public DefaultModelValidatorTest()
081        {
082            super();
083        }
084    
085        /**
086         * Gets the {@code DefaultModelValidator} instance tests are performed with.
087         *
088         * @return The {@code DefaultModelValidator} instance tests are performed with.
089         *
090         * @see #newModelValidator()
091         */
092        public DefaultModelValidator getModelValidator()
093        {
094            if ( this.defaultModelValidator == null )
095            {
096                this.defaultModelValidator = this.newModelValidator();
097            }
098    
099            return this.defaultModelValidator;
100        }
101    
102        /**
103         * Create a new {@code DefaultModelValidator} instance to test.
104         *
105         * @return A new {@code DefaultModelValidator} instance to test.
106         *
107         * @see #getModelValidator()
108         */
109        protected DefaultModelValidator newModelValidator()
110        {
111            return new DefaultModelValidator();
112        }
113    
114        /**
115         * Gets the {@code ModelContext} instance tests are performed with.
116         *
117         * @return The {@code ModelContext} instance tests are performed with.
118         *
119         * @see #newModelContext()
120         */
121        public ModelContext getModelContext()
122        {
123            if ( this.modelContext == null )
124            {
125                this.modelContext = this.newModelContext();
126                this.modelContext.getListeners().add( new ModelContext.Listener()
127                {
128    
129                    @Override
130                    public void onLog( final Level level, String message, Throwable t )
131                    {
132                        super.onLog( level, message, t );
133                        System.out.println( "[" + level.getLocalizedName() + "] " + message );
134                        if ( t != null )
135                        {
136                            t.printStackTrace( System.out );
137                        }
138                    }
139    
140                } );
141            }
142    
143            return this.modelContext;
144        }
145    
146        /**
147         * Creates a new {@code ModelContext} instance to perform tests with.
148         *
149         * @return A new {@code ModelContext} instance to perform tests with.
150         */
151        protected ModelContext newModelContext()
152        {
153            return ModelContextFactory.newInstance().newModelContext();
154        }
155    
156        /**
157         * Gets the {@code TestSuite} instance holding module tests to run.
158         *
159         * @return The {@code TestSuite} instance holding module tests to run.
160         *
161         * @see #newTestSuite()
162         */
163        public TestSuite getTestSuite()
164        {
165            if ( this.testSuite == null )
166            {
167                this.testSuite = this.newTestSuite();
168            }
169    
170            return this.testSuite;
171        }
172    
173        /**
174         * Creates a new {@code TestSuite} instance holding module tests to run.
175         *
176         * @return A new {@code TestSuite} instance holding module tests to run.
177         */
178        protected TestSuite newTestSuite()
179        {
180            try
181            {
182                return ( (JAXBElement<TestSuite>) this.getModelContext().createUnmarshaller(
183                    ModelObject.MODEL_PUBLIC_ID ).unmarshal( this.getClass().getResource(
184                    ABSOLUTE_RESOURCE_NAME_PREFIX + "DefaultModelValidatorTestSuite.xml" ) ) ).getValue();
185    
186            }
187            catch ( final JAXBException e )
188            {
189                throw new AssertionError( e );
190            }
191            catch ( final ModelException e )
192            {
193                throw new AssertionError( e );
194            }
195        }
196    
197        @Test
198        public final void testIllegalArguments() throws Exception
199        {
200            try
201            {
202                this.getModelValidator().validateModel( this.getModelContext(), null );
203                fail( "Expected NullPointerException not thrown." );
204            }
205            catch ( final NullPointerException e )
206            {
207                assertNotNull( e.getMessage() );
208                System.out.println( e.toString() );
209            }
210    
211            try
212            {
213                this.getModelValidator().validateModel( null, new Model() );
214                fail( "Expected NullPointerException not thrown." );
215            }
216            catch ( final NullPointerException e )
217            {
218                assertNotNull( e.getMessage() );
219                System.out.println( e.toString() );
220            }
221        }
222    
223        @Test
224        public final void testLegalArguments() throws Exception
225        {
226            assertNotNull( this.getModelValidator().validateModel(
227                this.getModelContext(), this.getModelContext().findModel( ModelObject.MODEL_PUBLIC_ID ) ) );
228    
229        }
230    
231        /**
232         * Runs a {@code SchemaConstraintsTestType} test.
233         *
234         * @param identifier The identifier of the {@code SchemaConstraintsTestType} to run.
235         *
236         * @throws Exception if running the test fails.
237         */
238        public final void testSchemaConstraints( final String identifier ) throws Exception
239        {
240            SchemaConstraintsTestType test = null;
241    
242            for ( SchemaConstraintsTestType candidate : this.getTestSuite().getSchemaConstraintsTest() )
243            {
244                if ( identifier.equals( candidate.getIdentifier() ) )
245                {
246                    test = candidate;
247                    break;
248                }
249            }
250    
251            assertNotNull( "Schema constraints test '" + identifier + "' not found.", test );
252    
253            final ModelContext context = this.getModelContext();
254            final JAXBContext jaxbContext = context.createContext( ModelObject.MODEL_PUBLIC_ID );
255    
256            System.out.println( "SchemaConstraintsTest: " + test.getIdentifier() );
257    
258            final JAXBElement<? extends ModelObject> modelObject =
259                (JAXBElement<? extends ModelObject>) test.getModelObject().getAny();
260    
261            final JAXBSource source = new JAXBSource( jaxbContext, modelObject );
262            final ModelValidationReport report = context.validateModel( ModelObject.MODEL_PUBLIC_ID, source );
263    
264            log( report );
265    
266            assertEquals( "[" + test.getIdentifier() + "]", test.getModelObject().isValid(), report.isModelValid() );
267        }
268    
269        /**
270         * Runs a {@code ModulesConstraintsTestType} test.
271         *
272         * @param identifier The identifier of the {@code ModulesConstraintsTestType} to run.
273         *
274         * @throws Exception if running the test fails.
275         */
276        public final void testModulesConstraints( final String identifier ) throws Exception
277        {
278            ModulesConstraintsTestType test = null;
279    
280            for ( ModulesConstraintsTestType candidate : this.getTestSuite().getModulesConstraintsTest() )
281            {
282                if ( identifier.equals( candidate.getIdentifier() ) )
283                {
284                    test = candidate;
285                    break;
286                }
287            }
288    
289            assertNotNull( "Modules constraints test '" + identifier + "' not found.", test );
290    
291            final ModelContext context = this.getModelContext();
292            System.out.println( "ModulesConstraintsTest: " + test.getIdentifier() );
293    
294            final JAXBElement<Modules> modules = (JAXBElement<Modules>) test.getModules().getAny();
295            final Model model = new Model();
296            model.setIdentifier( ModelObject.MODEL_PUBLIC_ID );
297            ModelHelper.setModules( model, modules.getValue() );
298    
299            final ModelValidationReport report = this.getModelValidator().validateModel( context, model );
300    
301            log( report );
302    
303            assertEquals( "[" + test.getIdentifier() + "] Unexpected model validity.",
304                          test.getModules().isValid(), report.isModelValid() );
305    
306            for ( ModelValidationReportDetail expectedDetail : test.getDetail() )
307            {
308                final List<ModelValidationReport.Detail> reportedDetails =
309                    report.getDetails( expectedDetail.getIdentifier() );
310    
311                assertTrue( "[" + test.getIdentifier() + "] Expected " + expectedDetail.getCount() + " "
312                            + expectedDetail.getIdentifier() + " details but got " + reportedDetails.size()
313                            + ".", expectedDetail.getCount() == reportedDetails.size() );
314    
315                report.getDetails().removeAll( reportedDetails );
316            }
317    
318            if ( !report.getDetails().isEmpty() )
319            {
320                for ( ModelValidationReport.Detail d : report.getDetails() )
321                {
322                    fail( "[" + test.getIdentifier() + "] Unexpected " + d.getIdentifier() + " detail." );
323                }
324            }
325        }
326    
327        private static void log( final ModelValidationReport report )
328        {
329            for ( ModelValidationReport.Detail d : report.getDetails() )
330            {
331                System.out.println( "\t" + d.toString() );
332            }
333        }
334    
335    }