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 }