001    // SECTION-START[License Header]
002    // <editor-fold defaultstate="collapsed" desc=" Generated License ">
003    /*
004     *   Copyright (c) 2010 The JOMC Project
005     *   Copyright (c) 2005 Christian Schulte <schulte2005@users.sourceforge.net>
006     *   All rights reserved.
007     *
008     *   Redistribution and use in source and binary forms, with or without
009     *   modification, are permitted provided that the following conditions
010     *   are met:
011     *
012     *     o Redistributions of source code must retain the above copyright
013     *       notice, this list of conditions and the following disclaimer.
014     *
015     *     o Redistributions in binary form must reproduce the above copyright
016     *       notice, this list of conditions and the following disclaimer in
017     *       the documentation and/or other materials provided with the
018     *       distribution.
019     *
020     *   THIS SOFTWARE IS PROVIDED BY THE JOMC PROJECT AND CONTRIBUTORS "AS IS"
021     *   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
022     *   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
023     *   PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JOMC PROJECT OR
024     *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025     *   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026     *   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
027     *   OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
028     *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
029     *   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
030     *   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031     *
032     *   $Id: SequenceDirectoryTest.java 2246 2010-06-29 07:59:25Z schulte2005 $
033     *
034     */
035    // </editor-fold>
036    // SECTION-END
037    package org.jomc.sequences.it;
038    
039    import java.io.IOException;
040    import java.io.InputStream;
041    import java.math.BigInteger;
042    import java.net.URL;
043    import java.util.ArrayList;
044    import java.util.Arrays;
045    import java.util.List;
046    import java.util.Set;
047    import java.util.logging.LogManager;
048    import org.jomc.sequences.ConcurrentModificationException;
049    import org.jomc.sequences.SequenceExistsException;
050    import org.jomc.sequences.SequenceVetoException;
051    import org.jomc.sequences.Sequence;
052    import org.jomc.sequences.SequenceNotFoundException;
053    import org.jomc.sequences.SequencesSystemException;
054    import org.junit.Test;
055    import org.junit.runner.JUnitCore;
056    import static org.junit.Assert.assertEquals;
057    import static org.junit.Assert.assertNotNull;
058    import static org.junit.Assert.fail;
059    
060    // SECTION-START[Documentation]
061    // <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
062    /**
063     * Testcase for SequenceDirectory implementations.
064     * <p><b>Properties</b><ul>
065     * <li>"{@link #getSequenceNameMaxLength sequenceNameMaxLength}"
066     * <blockquote>Property of type {@code int}.
067     * <p>Maximum allowed length of a sequence name.</p>
068     * </blockquote></li>
069     * <li>"{@link #getSequenceNameMinLength sequenceNameMinLength}"
070     * <blockquote>Property of type {@code int}.
071     * <p>Minimum required length of a sequence name.</p>
072     * </blockquote></li>
073     * </ul></p>
074     * <p><b>Dependencies</b><ul>
075     * <li>"{@link #getSequenceDirectory SequenceDirectory}"<blockquote>
076     * Dependency on {@code 'org.jomc.sequences.SequenceDirectory'} {@code (org.jomc.sequences.SequenceDirectory)} at specification level 1.0 bound to an instance.</blockquote></li>
077     * </ul></p>
078     *
079     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a> 1.0
080     * @version $Id: SequenceDirectoryTest.java 2246 2010-06-29 07:59:25Z schulte2005 $
081     */
082    // </editor-fold>
083    // SECTION-END
084    // SECTION-START[Annotations]
085    // <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
086    @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.0", comments = "See http://jomc.sourceforge.net/jomc/1.0/jomc-tools" )
087    // </editor-fold>
088    // SECTION-END
089    public class SequenceDirectoryTest
090    {
091        // SECTION-START[SequenceDirectoryTest]
092    
093        /**
094         * Gets a sequence with valid data.
095         *
096         * @return A sequence with valid data.
097         */
098        public static Sequence getTestSequence()
099        {
100            final Sequence legal = new Sequence();
101            legal.setIncrement( 1L );
102            legal.setMaximum( 10L );
103            legal.setMinimum( 0L );
104            legal.setName( "TEST" );
105            legal.setValue( 0L );
106    
107            return legal;
108        }
109    
110        /**
111         * Tests all {@link org.jomc.sequences.SequenceDirectory} methods to handle illegal arguments correctly by throwing
112         * a {@code SequencesSystemException} with non-null message.
113         */
114        @Test public void testIllegalArguments() throws Exception
115        {
116            assert this.getSequenceDirectory() != null;
117    
118            try
119            {
120                this.getSequenceDirectory().addSequence( null );
121                fail( "Expected SequencesSystemException not thrown." );
122            }
123            catch ( final SequencesSystemException e )
124            {
125                assertNotNull( e.getMessage() );
126                System.out.println( e.toString() );
127            }
128    
129            try
130            {
131                this.getSequenceDirectory().deleteSequence( null, 0L );
132                fail( "Expected SequencesSystemException not thrown." );
133            }
134            catch ( final SequencesSystemException e )
135            {
136                assertNotNull( e.getMessage() );
137                System.out.println( e.toString() );
138            }
139    
140            try
141            {
142                this.getSequenceDirectory().editSequence( null, 0L, null );
143                fail( "Expected SequencesSystemException not thrown." );
144            }
145            catch ( final SequencesSystemException e )
146            {
147                assertNotNull( e.getMessage() );
148                System.out.println( e.toString() );
149            }
150    
151            try
152            {
153                this.getSequenceDirectory().editSequence( "TEST", 0L, null );
154                fail( "Expected SequencesSystemException not thrown." );
155            }
156            catch ( final SequencesSystemException e )
157            {
158                assertNotNull( e.getMessage() );
159                System.out.println( e.toString() );
160            }
161    
162            try
163            {
164                this.getSequenceDirectory().editSequence( null, 0L, new Sequence() );
165                fail( "Expected SequencesSystemException not thrown." );
166            }
167            catch ( final SequencesSystemException e )
168            {
169                assertNotNull( e.getMessage() );
170                System.out.println( e.toString() );
171            }
172    
173            try
174            {
175                this.getSequenceDirectory().getSequence( null );
176                fail( "Expected SequencesSystemException not thrown." );
177            }
178            catch ( final SequencesSystemException e )
179            {
180                assertNotNull( e.getMessage() );
181                System.out.println( e.toString() );
182            }
183    
184        }
185    
186        /** Tests that a valid sequence can get added, edited, searched and removed. */
187        @Test public void testAddEditSearchDeleteLegalSequence() throws Exception
188        {
189            assert this.getSequenceDirectory() != null;
190    
191            this.clearDirectory();
192    
193            Sequence legal = getTestSequence();
194    
195            legal = this.getSequenceDirectory().addSequence( legal );
196    
197            System.out.println( legal );
198    
199            legal.setName( "TEST2" );
200    
201            legal = this.getSequenceDirectory().editSequence( "TEST", legal.getRevision(), legal );
202    
203            System.out.println( legal );
204    
205            assertEquals( legal, this.getSequenceDirectory().getSequence( "TEST2" ) );
206    
207            final Set<Sequence> result = this.getSequenceDirectory().searchSequences( "%TEST%" );
208    
209            assertEquals( 1, result.size() );
210            assertEquals( legal, result.toArray()[0] );
211    
212            this.getSequenceDirectory().deleteSequence( "TEST2", legal.getRevision() );
213    
214            assertEquals( 0, this.getSequenceDirectory().searchSequences( null ).size() );
215            assertEquals( BigInteger.ZERO, this.getSequenceDirectory().getSequenceCount() );
216        }
217    
218        /** Tests that a sequence cannot get edited or removed when it got changed concurrently. */
219        @Test public void testConcurrentModificationException() throws Exception
220        {
221            assert this.getSequenceDirectory() != null;
222    
223            this.clearDirectory();
224    
225            final Sequence legal = getTestSequence();
226    
227            final Sequence sequence = this.getSequenceDirectory().addSequence( legal );
228    
229            try
230            {
231                this.getSequenceDirectory().editSequence( "TEST", sequence.getRevision() + 1L, sequence );
232                fail( "Expected ConcurrentModificationException not thrown." );
233            }
234            catch ( final ConcurrentModificationException e )
235            {
236                assertNotNull( e.getMessage() );
237                System.out.println( e.toString() );
238            }
239    
240            try
241            {
242                this.getSequenceDirectory().deleteSequence( "TEST", sequence.getRevision() + 1L );
243                fail( "Expected ConcurrentModificationException not thrown." );
244            }
245            catch ( final ConcurrentModificationException e )
246            {
247                assertNotNull( e.getMessage() );
248                System.out.println( e.toString() );
249            }
250        }
251    
252        /**
253         * Tests that adding an illegal sequence or updating an existing sequence with illegal data is prevented by throwing
254         * a corresponding {@code SequenceVetoException}.
255         */
256        @Test public void testSequenceVetoException() throws Exception
257        {
258            assert this.getSequenceDirectory() != null;
259    
260            this.clearDirectory();
261    
262            Sequence legal = getTestSequence();
263    
264            final Sequence illegal = new Sequence();
265            char[] name = new char[ this.getSequenceNameMaxLength() + 1 ];
266            Arrays.fill( name, 'T' );
267    
268            illegal.setName( String.valueOf( name ) );
269            illegal.setMinimum( 100L );
270            illegal.setMaximum( 1L );
271            illegal.setValue( 0L );
272            illegal.setIncrement( -1L );
273    
274            try
275            {
276                this.getSequenceDirectory().addSequence( illegal );
277                fail( "Expected SequenceVetoException not thrown." );
278            }
279            catch ( final SequenceVetoException e )
280            {
281                assertNotNull( e.getMessage() );
282                System.out.println( e.toString() );
283            }
284    
285            illegal.setName( null );
286    
287            try
288            {
289                this.getSequenceDirectory().addSequence( illegal );
290                fail( "Expected SequenceVetoException not thrown." );
291            }
292            catch ( final SequenceVetoException e )
293            {
294                assertNotNull( e.getMessage() );
295                System.out.println( e.toString() );
296            }
297    
298            if ( this.getSequenceNameMinLength() - 1 >= 0 )
299            {
300                try
301                {
302                    name = new char[ this.getSequenceNameMinLength() - 1 ];
303                    Arrays.fill( name, 'T' );
304                    illegal.setName( String.valueOf( name ) );
305                    this.getSequenceDirectory().addSequence( illegal );
306                    fail( "Expected SequenceVetoException not thrown." );
307                }
308                catch ( final SequenceVetoException e )
309                {
310                    assertNotNull( e.getMessage() );
311                    System.out.println( e.toString() );
312                }
313            }
314    
315            legal = this.getSequenceDirectory().addSequence( legal );
316    
317            try
318            {
319                this.getSequenceDirectory().editSequence( legal.getName(), legal.getRevision(), illegal );
320                fail( "Expected SequenceVetoException not thrown." );
321            }
322            catch ( final SequenceVetoException e )
323            {
324                assertNotNull( e.getMessage() );
325                System.out.println( e.toString() );
326            }
327    
328            this.getSequenceDirectory().deleteSequence( legal.getName(), legal.getRevision() );
329        }
330    
331        /**
332         * Tests that adding a sequence twice is prevented by throwing a corresponding {@code SequenceExistsException}.
333         */
334        @Test public void testSequenceExistsException() throws Exception
335        {
336            assert this.getSequenceDirectory() != null;
337    
338            this.clearDirectory();
339    
340            Sequence legal = getTestSequence();
341    
342            legal = this.getSequenceDirectory().addSequence( legal );
343    
344            try
345            {
346                this.getSequenceDirectory().addSequence( legal );
347                fail( "Expected SequenceExistsException not thrown." );
348            }
349            catch ( final SequenceExistsException e )
350            {
351                assertNotNull( e.getMessage() );
352                System.out.println( e.toString() );
353            }
354        }
355    
356        /**
357         * Tests that updating or deleting an unknown sequence is prevented by throwing a corresponding
358         * {@code SequenceNotFoundException}.
359         */
360        @Test public void testSequenceNotFoundException() throws Exception
361        {
362            assert this.getSequenceDirectory() != null;
363    
364            this.clearDirectory();
365    
366            final Sequence legal = getTestSequence();
367    
368            try
369            {
370                this.getSequenceDirectory().editSequence( "UNKNOWN", 0L, legal );
371                fail( "Expected SequenceNotFoundException not thrown." );
372            }
373            catch ( final SequenceNotFoundException e )
374            {
375                assertNotNull( e.getMessage() );
376                System.out.println( e.toString() );
377            }
378    
379            try
380            {
381                this.getSequenceDirectory().deleteSequence( "UNKNOWN", 0L );
382                fail( "Expected SequenceNotFoundException not thrown." );
383            }
384            catch ( final SequenceNotFoundException e )
385            {
386                assertNotNull( e.getMessage() );
387                System.out.println( e.toString() );
388            }
389    
390            this.clearDirectory();
391        }
392    
393        /** Tests that adding, editing and then removing multiple sequences leaves an empty directory. */
394        @Test public void testAddEditDeleteMany() throws Exception
395        {
396            assert this.getSequenceDirectory() != null;
397    
398            this.clearDirectory();
399    
400            final int count = 15;
401            final List<Sequence> added = new ArrayList<Sequence>( count );
402            final List<Sequence> updated = new ArrayList<Sequence>( count );
403            for ( int i = 0; i < count; i++ )
404            {
405                final Sequence legal = getTestSequence();
406                legal.setName( legal.getName() + ' ' + i );
407                final Sequence a = this.getSequenceDirectory().addSequence( legal );
408                added.add( a );
409                System.out.println( "ADD: " + a );
410            }
411    
412            for ( Sequence s : added )
413            {
414                final String oldName = s.getName();
415                s.setName( oldName + "_UPDATED" );
416    
417                final Sequence u = this.getSequenceDirectory().editSequence( oldName, s.getRevision(), s );
418                updated.add( u );
419    
420                System.out.println( "EDIT: " + u );
421            }
422    
423            for ( Sequence s : updated )
424            {
425                final Sequence d = this.getSequenceDirectory().deleteSequence( s.getName(), s.getRevision() );
426                System.out.println( "DELETE: " + d );
427            }
428    
429            assertEquals( BigInteger.ZERO, this.getSequenceDirectory().getSequenceCount() );
430        }
431    
432        /** Removes all sequences from the directory. */
433        protected void clearDirectory() throws Exception
434        {
435            // Remove any test entries.
436            for ( Sequence sequence : this.getSequenceDirectory().searchSequences( null ) )
437            {
438                System.out.println( this.getSequenceDirectory().deleteSequence(
439                    sequence.getName(), sequence.getRevision() ) );
440    
441            }
442    
443            assertEquals( BigInteger.ZERO, this.getSequenceDirectory().getSequenceCount() );
444        }
445    
446        /**
447         * Test runner entry point.
448         * <p>This method sets up the JDK's {@code LogManager} with properties found at classpath location
449         * {@code "/logging.properties"} and executes {@link JUnitCore#main} passing the given arguments with this classes
450         * name prepended.</p>
451         *
452         * @param args Command line arguments.
453         */
454        public static void main( final String... args )
455        {
456            try
457            {
458                final URL loggingProperties = SequenceDirectoryTest.class.getResource( "/logging.properties" );
459                if ( loggingProperties != null )
460                {
461                    final InputStream in = loggingProperties.openStream();
462                    LogManager.getLogManager().readConfiguration( in );
463                    in.close();
464                }
465    
466                final List<String> l = new ArrayList<String>( Arrays.asList( args ) );
467                l.add( 0, SequenceDirectoryTest.class.getName() );
468                JUnitCore.main( l.toArray( new String[ l.size() ] ) );
469            }
470            catch ( final IOException e )
471            {
472                e.printStackTrace();
473                System.exit( 1 );
474            }
475        }
476    
477        // SECTION-END
478        // SECTION-START[Constructors]
479        // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
480    
481        /** Creates a new {@code SequenceDirectoryTest} instance. */
482        @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.0", comments = "See http://jomc.sourceforge.net/jomc/1.0/jomc-tools" )
483        public SequenceDirectoryTest()
484        {
485            // SECTION-START[Default Constructor]
486            super();
487            // SECTION-END
488        }
489        // </editor-fold>
490        // SECTION-END
491        // SECTION-START[Dependencies]
492        // <editor-fold defaultstate="collapsed" desc=" Generated Dependencies ">
493    
494        /**
495         * Gets the {@code SequenceDirectory} dependency.
496         * <p>This method returns any available object of the {@code 'org.jomc.sequences.SequenceDirectory'} {@code (org.jomc.sequences.SequenceDirectory)} specification at specification level 1.0.</p>
497         * <p>That specification applies to {@code Singleton} scope. The singleton object is returned whenever requested and bound to this instance.</p>
498         * @return The {@code SequenceDirectory} dependency.
499         * {@code null} if no object is available.
500         * @throws org.jomc.ObjectManagementException if getting the dependency instance fails.
501         */
502        @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.0", comments = "See http://jomc.sourceforge.net/jomc/1.0/jomc-tools" )
503        private org.jomc.sequences.SequenceDirectory getSequenceDirectory()
504        {
505            return (org.jomc.sequences.SequenceDirectory) org.jomc.ObjectManagerFactory.getObjectManager( this.getClass().getClassLoader() ).getDependency( this, "SequenceDirectory" );
506        }
507        // </editor-fold>
508        // SECTION-END
509        // SECTION-START[Properties]
510        // <editor-fold defaultstate="collapsed" desc=" Generated Properties ">
511    
512        /**
513         * Gets the value of the {@code sequenceNameMaxLength} property.
514         * @return Maximum allowed length of a sequence name.
515         * @throws org.jomc.ObjectManagementException if getting the property instance fails.
516         */
517        @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.0", comments = "See http://jomc.sourceforge.net/jomc/1.0/jomc-tools" )
518        private int getSequenceNameMaxLength()
519        {
520            final java.lang.Integer _p = (java.lang.Integer) org.jomc.ObjectManagerFactory.getObjectManager( this.getClass().getClassLoader() ).getProperty( this, "sequenceNameMaxLength" );
521            assert _p != null : "'sequenceNameMaxLength' property not found.";
522            return _p.intValue();
523        }
524    
525        /**
526         * Gets the value of the {@code sequenceNameMinLength} property.
527         * @return Minimum required length of a sequence name.
528         * @throws org.jomc.ObjectManagementException if getting the property instance fails.
529         */
530        @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.0", comments = "See http://jomc.sourceforge.net/jomc/1.0/jomc-tools" )
531        private int getSequenceNameMinLength()
532        {
533            final java.lang.Integer _p = (java.lang.Integer) org.jomc.ObjectManagerFactory.getObjectManager( this.getClass().getClassLoader() ).getProperty( this, "sequenceNameMinLength" );
534            assert _p != null : "'sequenceNameMinLength' property not found.";
535            return _p.intValue();
536        }
537        // </editor-fold>
538        // SECTION-END
539        // SECTION-START[Messages]
540        // SECTION-END
541    }