/* * class: SequentialRecordLoopNoRunTest * * Version $Id: SequentialRecordLoopNoRunTest.java 8584 2006-08-10 23:06:37Z duns $ * * Date: February 9 2003 * * (c) 2003 LBNL */ package org.freehep.record.loop.test; import org.freehep.record.loop.LoopException; import org.freehep.record.loop.LoopSourceExhaustedException; import org.freehep.record.loop.SequentialRecordLoop; import org.freehep.record.loop.event.ConfigurationEvent; import org.freehep.record.loop.event.RecordSuppliedEvent; import org.freehep.record.source.EndOfSourceException; import org.freehep.record.source.SequentialRecordSource; import junit.framework.*; import java.io.IOException; import java.util.TooManyListenersException; /** * This class defines the tests that any SequentialRecordLoop object should pass. * * @version $Id: SequentialRecordLoopNoRunTest.java 8584 2006-08-10 23:06:37Z duns $ * @author patton */ public abstract class SequentialRecordLoopNoRunTest extends TestCase { // public static final member data // protected static final member data protected static final Object[] TEST_OBJECTS = new Object[]{ new Object(), new Object(), new Object(), new Object(), new Object() }; protected static final boolean[] TEST_MIXED_RECORDS = new boolean[]{ false, true, true, false, true, }; protected static final long TEST_MIXED_EVENT_COUNT = 3; // static final member data // private static final member data private static final Object TEST_CONFIGURATION = new Object(); private static final Object TEST_RECONFIGURATION = new Object(); // private static member data // private instance member data /** The object being tested. */ private SequentialRecordLoop testObject; /** The listener being used in testing. */ private MockListener listener; // constructors /** * Create an instance of this class. * Default constructor is declared, but private, to stop accidental * creation of an instance of the class. */ private SequentialRecordLoopNoRunTest() { super(null); } /** * Constructs and instance of this test. * @param name */ public SequentialRecordLoopNoRunTest(String name) { super(name); } // instance member function (alphabetic) /** * Sets the object to be tested. * * @param testObject object to be tested. */ protected void setRecordLoop(SequentialRecordLoop testObject) { this.testObject = testObject; testObject.setRecordSource(new MockRecordSource(TEST_OBJECTS)); } /** * Sets up the fixture, for example, open a network connection. * This method is called before a test is executed. */ protected void setUp() { testObject.setConfiguration(TEST_CONFIGURATION); } /** * Tears down the fixture, for example, close a network connection. * This method is called after a test is executed. */ protected void tearDown() { testObject = null; } /** * Test that the configure message is correctly handled. */ public void testConfigure() { testSuspend(); } /** * Test that default sequence runs correctly. */ public void testDefaultSequence() { testListenerAdd(); try { testObject.loop(-1); } catch (LoopException e1) { fail("Threw LoopException Exception\n" + e1.toString()); } catch (IOException e2) { fail("Threw IOException Exception\n" + e2.toString()); } } /** * Test that it is not possible to add two RecordListener this object. */ public void testDoubleAdd() { testListenerAdd(); try { testObject.addRecordListener(new MockListener()); fail("Was able to add two RecordListener objects"); } catch (TooManyListenersException e) { } } /** * Test that the end of source condition is correctly reported. */ public void testEndOfSource() { testListenerAdd(); try { testObject.loop(TEST_OBJECTS.length + 1); fail("LoopSourceExhaustedException was not thrown!"); } catch (LoopException e1) { if (e1 instanceof LoopSourceExhaustedException) { } else { fail("Threw LoopException Exception\n" + e1.toString()); } } catch (IOException e2) { fail("Threw IOException Exception\n" + e2.toString()); } } /** * Test that the finish message is correctly handled. */ public void testFinish() { byte[] stateSequence = {StateMachineTester.READY_STATE, StateMachineTester.CONFIGURED_STATE, StateMachineTester.SUSPENDED_STATE, StateMachineTester.READY_STATE}; testListenerAdd(); listener.setStates(stateSequence); try { testObject.loop(0); } catch (LoopException e1) { fail("Threw LoopException Exception\n" + e1.toString()); } catch (IOException e2) { fail("Threw IOException Exception\n" + e2.toString()); } testObject.dispose(); } /** * Test that this object can be interrupted. This is dependent on the * implementation of the SequentialRecordLoop so must be provided by its test class. */ public abstract void testInterrupt(); /** * Test that the interrupt flag gets cleared after an interrupt has * been serviced. */ public void testInterruptCleared() { testInterrupt(); assertTrue(!testObject.isInterruptRequested()); } /** * Test that an RecordListener can be added to this object. */ public void testListenerAdd() { listener = new MockListener(); try { testObject.addRecordListener(listener); } catch (TooManyListenersException e) { fail("Threw TooManyListener Exception\n" + e.toString()); } } /** * Test that an RecordListener can be removed from this object. */ public void testListenerRemove() { testListenerAdd(); testObject.removeRecordListener(listener); try { testObject.addRecordListener(new MockListener()); } catch (TooManyListenersException e) { fail("Threw TooManyListener Exception\n" + e.toString()); } } /** * Test that the event count for mixed records correct. */ public void testMixedCount() { testListenerAdd(); listener.setRecords(TEST_OBJECTS, TEST_MIXED_RECORDS); try { long result = testObject.loop(TEST_MIXED_EVENT_COUNT); assertEquals(TEST_MIXED_EVENT_COUNT, result); assertEquals(TEST_OBJECTS.length, testObject.getTotalSupplied()); assertEquals(TEST_MIXED_EVENT_COUNT, testObject.getTotalCountableSupplied()); } catch (LoopException e1) { fail("Threw LoopException Exception\n" + e1.toString()); } catch (IOException e2) { fail("Threw IOException Exception\n" + e2.toString()); } } /** * Test that the event count for pure records correct. */ public void testPureCount() { testListenerAdd(); listener.setRecords(TEST_OBJECTS); try { long result = testObject.loop(TEST_OBJECTS.length); assertEquals(TEST_OBJECTS.length, result); assertEquals(TEST_OBJECTS.length, testObject.getTotalSupplied()); assertEquals(TEST_OBJECTS.length, testObject.getTotalCountableSupplied()); } catch (LoopException e1) { fail("Threw LoopException Exception\n" + e1.toString()); } catch (IOException e2) { fail("Threw IOException Exception\n" + e2.toString()); } } /** * Test that the recordSupplied message is correctly handled. */ public void testRecordSupplied() { byte[] stateSequence = {StateMachineTester.READY_STATE, StateMachineTester.CONFIGURED_STATE, StateMachineTester.PROCESSING_STATE, StateMachineTester.SUSPENDED_STATE}; testListenerAdd(); listener.setStates(stateSequence); try { testObject.loop(1); } catch (LoopException e1) { fail("Threw LoopException Exception\n" + e1.toString()); } catch (IOException e2) { fail("Threw IOException Exception\n" + e2.toString()); } } /** * Test that the reconfigure message is correctly handled. */ public void testReconfigure() { byte[] stateSequence = {StateMachineTester.READY_STATE, StateMachineTester.CONFIGURED_STATE, StateMachineTester.PROCESSING_STATE, StateMachineTester.SUSPENDED_STATE, StateMachineTester.CONFIGURED_STATE, StateMachineTester.SUSPENDED_STATE}; testListenerAdd(); listener.setStates(stateSequence); try { testObject.loop(1); testObject.setConfiguration(TEST_RECONFIGURATION); testObject.loop(0); } catch (LoopException e1) { fail("Threw LoopException Exception\n" + e1.toString()); } catch (IOException e2) { fail("Threw IOException Exception\n" + e2.toString()); } } /** * Test test the null Listener can be handled. */ public void testNullListener() { try { testObject.loop(-1); } catch (LoopException e1) { fail("Threw LoopException Exception\n" + e1.toString()); } catch (IOException e2) { fail("Threw IOException Exception\n" + e2.toString()); } assertEquals(TEST_OBJECTS.length, testObject.getTotalCountableSupplied()); } /** * Test that removal of the null RecordListener does nothing wrong. */ public void testNullListenerRemove() { testListenerAdd(); testObject.removeRecordListener(null); } /** * Test that the resume message is correctly handled. */ public void testResume() { byte[] stateSequence = {StateMachineTester.READY_STATE, StateMachineTester.CONFIGURED_STATE, StateMachineTester.PROCESSING_STATE, StateMachineTester.SUSPENDED_STATE, StateMachineTester.CONFIGURED_STATE, StateMachineTester.SUSPENDED_STATE}; testListenerAdd(); listener.setStates(stateSequence); try { testObject.loop(1); testObject.loop(0); } catch (LoopException e1) { fail("Threw LoopException Exception\n" + e1.toString()); } catch (IOException e2) { fail("Threw IOException Exception\n" + e2.toString()); } } /** * Test that the suspend message is correctly handled. */ public void testSuspend() { byte[] stateSequence = {StateMachineTester.READY_STATE, StateMachineTester.CONFIGURED_STATE, StateMachineTester.SUSPENDED_STATE}; testListenerAdd(); listener.setStates(stateSequence); try { testObject.loop(0); } catch (LoopException e1) { fail("Threw LoopException Exception\n" + e1.toString()); } catch (IOException e2) { fail("Threw IOException Exception\n" + e2.toString()); } } /** * Test that removal of the wrong RecordListener does nothing wrong. */ public void testWrongListenerRemove() { testListenerAdd(); testObject.removeRecordListener(new MockListener()); } // static member functions (alphabetic) protected class MockRecordSource implements SequentialRecordSource { /** The sequence of object to serve out. */ private Object[] objects; /** Index the the current object in the sequence */ private int objectIndex = -1; /** * @param records an sequence of object to serve out. */ MockRecordSource(Object[] objects) { this.objects = objects; } public Class getRecordClass() { return Object.class; } public Object getCurrentRecord() throws EndOfSourceException { if (objectIndex >= objects.length) { throw new EndOfSourceException("Ran out of records in array"); } Object object = null; if (null != objects) { object = objects[objectIndex]; } return object; } public long getEstimatedSize() { return objects.length; } public String getSourceName() { return "MockSource"; } public void next() { objectIndex++; } public void releaseRecord(Object object) { } public void rewind() { objectIndex = 0; } public void close() throws IOException { } } private class MockListener extends StateMachineTester { /** The sequence of expected states. */ private byte[] states; /** Index the the current state in its sequence */ private int stateIndex; /** The sequence of expected records. */ private Object[] records; /** True if the record with the matching index should be counted. */ private boolean[] countibility; /** Index the the current Object in its sequence */ private int recordIndex; public void configure(ConfigurationEvent event) { Assert.assertEquals(TEST_CONFIGURATION, event.getConfiguration()); super.configure(event); } public void recordSupplied(RecordSuppliedEvent event) { if (null != records) { Assert.assertSame(records[recordIndex], event.getRecord()); if ((null != countibility) && (!countibility[recordIndex])) { event.getRecordLoop().doNotCount(event.getRecord()); } recordIndex++; } super.recordSupplied(event); } public void reconfigure(ConfigurationEvent event) { Assert.assertEquals(TEST_RECONFIGURATION, event.getConfiguration()); super.reconfigure(event); } /** * @param sets the sequence of expected records. */ public void setRecords(Object[] records) { this.records = records; } /** * @param sets the sequence of expected records with their associated * countablilty flags. */ public void setRecords(Object[] records, boolean[] countability) { this.records = records; this.countibility = countability; } /** * @param sets the sequence of expected transitions. */ public void setStates(byte[] states) { this.states = states; } /** * Check each transition matches the set list. */ protected void setState(byte state) { if (null != states) { Assert.assertTrue(isState(states[stateIndex])); stateIndex++; Assert.assertEquals(state, states[stateIndex]); } super.setState(state); } } /** * Create test suite for this class. */ public static Test suite() { return new TestSuite(SequentialRecordLoopNoRunTest.class); } // Description of this object. // public String toString() {} }