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 4613 2012-09-22 10:07:08Z schulte $
029 *
030 */
031package org.jomc.model.modlet.test;
032
033import java.util.List;
034import java.util.logging.Level;
035import javax.xml.bind.JAXBContext;
036import javax.xml.bind.JAXBElement;
037import javax.xml.bind.JAXBException;
038import javax.xml.bind.util.JAXBSource;
039import org.jomc.model.ModelObject;
040import org.jomc.model.Modules;
041import org.jomc.model.modlet.DefaultModelValidator;
042import org.jomc.model.modlet.ModelHelper;
043import org.jomc.model.test.ModelValidationReportDetail;
044import org.jomc.model.test.ModulesConstraintsTestType;
045import org.jomc.model.test.SchemaConstraintsTestType;
046import org.jomc.model.test.TestSuite;
047import org.jomc.modlet.Model;
048import org.jomc.modlet.ModelContext;
049import org.jomc.modlet.ModelContextFactory;
050import org.jomc.modlet.ModelException;
051import org.jomc.modlet.ModelValidationReport;
052import org.junit.Test;
053import static org.junit.Assert.assertEquals;
054import static org.junit.Assert.assertNotNull;
055import static org.junit.Assert.assertTrue;
056import 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:cs@schulte.it">Christian Schulte</a> 1.0
062 * @version $JOMC: DefaultModelValidatorTest.java 4613 2012-09-22 10:07:08Z schulte $
063 */
064public 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}