[r3046]: test / releases / 3.1.2 / tests / oorexxunit / ooRexx / base / class / ooRexx.Base.Class.Queue.testUnit  Maximize  Restore  History

Download this file

1069 lines (840 with data), 37.7 kB

#!/usr/bin/rexx
/*
   name:             ooRexx.Base.Class.Queue.testUnit
   author:           Mark Miesfeld
   date:             2005-12-29
   version:          0.0.2

   changed:

   languageLevel:    6.0
   purpose:          Regression test for the Open Object REXX supplied .queue class.
   remark:           Work in progress at this time.  Tests for some methods are
                     simply place holders, the actual tests need to be filled in.

   license:          CPL 1.0 (Common Public License v1.0, see below)
   link:

   category:         ooRexx
   category:         Base
   category:         Class
   category:         Queue
*/
/*----------------------------------------------------------------------------*/
/*                                                                            */
/* Copyright (c) 2005 Rexx Language Association. All rights reserved.         */
/*                                                                            */
/* This program and the accompanying materials are made available under       */
/* the terms of the Common Public License v1.0 which accompanies this         */
/* distribution. A copy is also available at the following address:           */
/* http://www.oorexx.org/license.html                                         */
/*                                                                            */
/* Redistribution and use in source and binary forms, with or                 */
/* without modification, are permitted provided that the following            */
/* conditions are met:                                                        */
/*                                                                            */
/* Redistributions of source code must retain the above copyright             */
/* notice, this list of conditions and the following disclaimer.              */
/* Redistributions in binary form must reproduce the above copyright          */
/* notice, this list of conditions and the following disclaimer in            */
/* the documentation and/or other materials provided with the distribution.   */
/*                                                                            */
/* Neither the name of Rexx Language Association nor the names                */
/* of its contributors may be used to endorse or promote products             */
/* derived from this software without specific prior written permission.      */
/*                                                                            */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        */
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          */
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS          */
/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT   */
/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,      */
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED   */
/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,        */
/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY     */
/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING    */
/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         */
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.               */
/*                                                                            */
/*----------------------------------------------------------------------------*/

-- Create the test case list, (use all methods whose names start with test.)
testUnitList=.list~of( .array~of( .ooRexx.Base.Class.Queue.testUnit, .list~new ) );

-- Turn on extra messaging, if requested.  This feature is used for debugging
-- this specific test unit.  If this test unit is called by itself the caller
-- can specify that the test unit be more *verbose*.
.ooRexx.Base.Class.Queue.testUnit~setVerbose( arg( 1 ) );

-- Read this program file's metadata and save it in the TestCaseInfo attribute
-- of each test case class.
arrLines = .array~new;
do i = 1 to 150 until arrLines[ i ] = "*/"
   arrLines[ i ] = sourceline( i )
end

aTestUnitClass = testUnitList~at( testUnitList~first )[ 1 ];

call makeDirTestInfo aTestUnitClass, arrLines;

directoryObj = aTestUnitClass~TestCaseInfo;
parse source s;
directoryObj~setentry( "test_Case-source", s );

-- Now add this directory object to any other TestCase classes in the list.
-- (In this specific case, there are no other TestCase classes.  This is left
-- as a template for other TestCase files.)
do arr over testUnitList
   if arr[ 1 ] = aTestUnitClass then
     iterate;  -- Already handled.
   arr[ 1 ]~TestCaseInfo = directoryObj;
end

-- Check if we should execute the test cases now or return the test case list
-- to a caller.
if \ .local~hasentry( "bRunTestsLocally" ) then
   .local~bRunTestsLocally = .true

-- Run all tests in this test unit, if requested.
if .bRunTestsLocally = .true then do
  suite = .TestSuite~new;

  rrc =  addTestCases( suite, testUnitList );
  if rrc <> 0 then do
    say "ooRexx.Base.Class.Queue.testUnit:";
    say "  Some type of internal error, addTestCases( ) returns an error code.";
    say "    Return code:" rrc;
    say;
    return testUnitList;
  end

  -- Run the tests.
  z = time( 'E' );
  testResult = suite~run;

  if .ooRexx.Base.Class.Queue.TestUnit~verbose > 0 then
    say 'Executing all tests took' time( 'R' ) 'seconds.'

  -- Print the results.
  call simpleDumpTestResults testResult
end

-- Return the test case list.
return testUnitList
-- End of entry point.

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
  Directives, Classes, or Routines.
\* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
::requires 'OOREXXUNIT.CLS';

/* addTestCases( suite, list ) - - - - - - - - - - - - - - - - - - - - - - - -*\

  Adds all test cases in the specified list to the specified TestSuite.

  Input:
    suite REQUIRED
      A TestSuite object in which to add the test cases.

    list  REQUIRED
      A list of test cases, needs to be in the format Rony G. Flatscher defined
      in his original implementation of ooRexxUnit.

  Returns:
    0 on success; 1 if either argument is incorrect, 2 if some other error
    occurred.
\* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
::routine  addTestCases public;
  use arg suite, list;

  -- Check that args are the right type of objects, also handles omitted args.
  if suite~class <> .TestSuite | list~class <> .list then
    return 1;

  do arr over list
    if arr~class <> .array then
      return 2;

    classObject    = arr[ 1 ];
    mandatoryTests = arr[ 2 ];
    if classObject~class <> .class then
      return 2;

    -- See if a list of mandatory tests or all methods starting with 'test' is
    -- indicated.
    bMandatoryTests = .false;
    if mandatoryTests <> .nil then
      if mandatoryTests~class == .list then
        if mandatoryTests~items > 0 then
          bMandatoryTests = .true;

    if bMandatoryTests then do testMethodName over mandatoryTests
      -- Create and add a TestCase object
      suite~addTest( classObject~new( testMethodName ) );
    end
    else do
      -- Create and add a TestSuite object (all methods starting with 'test' in
      -- the class will be used as test cases.)
      suite~addTest( .TestSuite~new( classObject ) );
    end
  end
  -- End do arr over list

return 0;
-- End addTestCases( suite, list )

/* class: ooRexx.Base.Class.Queue.TestUnit - - - - - - - - - - - - - - - - - -*\

    A test case class to regression test the .queue class.  The .queue class is
    one of the 'collection' classes supplied by Open Object REXX.

    All test case methods in this class begin with 'test_'.

    The design specification used for these test cases of the .queue class is
    the current documentation for the class from:

      Open Object Rexx
      Reference
      Version 3.0.0 Revision 3 Edition
      November 11, 2005

\* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
::class "ooRexx.Base.Class.Queue.TestUnit" public subclass TestCase;

  /* test_new( ) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Test the .queue class method: new.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  test_new;

    if self~class~verbose > 2 then
      say '*In test_new';

    -- Prefix to my messages.
    be   = "New object should be";
    have = "New object should have"

    -- Create what should be a new instance of a queue.
    q = .queue~new;

    -- Test that the object is indeed an instance of .queue.
    self~assertEquals( be "instance of .queue", .queue, q~class );

    -- Test that the new object is a direct subclass of .object.
    supers = q~class~superclasses;
    self~assertEquals( have "only 1 superclass",     1,       supers~items );
    self~assertEquals( have ".object as superclass", .object, supers[ 1 ]  );

    -- Test that the object has all the .queue methods.
    self~assertTrue( have '"[]" method',      q~hasmethod( "[]"        ) );
    self~assertTrue( have '"[]=" method',     q~hasmethod( "[]="       ) );
    self~assertTrue( have "AT method",        q~hasmethod( "AT"        ) );
    self~assertTrue( have "HASINDEX method",  q~hasmethod( "HASINDEX"  ) );
    self~assertTrue( have "ITEMS method",     q~hasmethod( "ITEMS"     ) );
    self~assertTrue( have "MAKEARRAY method", q~hasmethod( "MAKEARRAY" ) );
    self~assertTrue( have "PEEK method",      q~hasmethod( "PEEK"      ) );
    self~assertTrue( have "PULL method",      q~hasmethod( "PULL"      ) );
    self~assertTrue( have "PUSH method",      q~hasmethod( "PUSH"      ) );
    self~assertTrue( have "PUT method",       q~hasmethod( "PUT"       ) );
    self~assertTrue( have "QUEUE method",     q~hasmethod( "QUEUE"     ) );
    self~assertTrue( have "REMOVE method",    q~hasmethod( "REMOVE"    ) );
    self~assertTrue( have "SUPPLIER method",  q~hasmethod( "SUPPLIER"  ) );

    -- Test that the queue is created empty.
    self~assertEquals( be "empty", 0, q~items );

  -- End test_new( )

  /* test_newReptitively( )- - - - - - - - - - - - - - - - - - - - - - - - - -*\

      Test that a lot of new, functional, .queue objects can be created and
      that each object is unique.

      I know, what is "a lot?"  This is not meant to be a stress test.  100,000
      should be sufficient.

      On my laptop with an Intel Mobil Pentium III Processor-M @ 1066 Mhz and
      512 MB of ram, this test takes about 5.1 seconds and uses about 35 MB of
      ram.  So, I do not think it is un-reasonably long or uses too much of the
      system resources.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  test_newReptitively;

    z = time( 'E' );

    if self~class~verbose > 2 then
      say '*In test_newReptitively';

    /* Used to control running of the lengthier test during implementation.
     * There is some debate in my mind whether this test should be included or
     * not.  The value of a regression suite is that it can be run quickly as a
     * sanity test.  Does running this test add too much time to a regression
     * suite?
     */
    /*
    if self~class~verbose < 4 then do
      say 'ooRexx.Base.Class.Queue.testUnit:';
      say '  Skipping lengthy test_newReptitively test.';
      say;
      return;
    end
    */

    holder = .set~new;
    count  = 100000;
    do count
      q = .queue~new;
      q~~queue( 'one' )~~queue( 'two' )~~queue( 'three' );
      holder~put( q );
    end

    self~assertEquals( "Expected to create" count "unique queues", count, holder~items );

    iterator = holder~supplier;
    lastObj  = .queue~new;
    i        = 0;
    do while iterator~available;
      obj = iterator~item;
      self~assertEquals( "Every new object should be instance of queue",  .queue, obj~class );
      self~assertEquals( "Each new queue object should now have 3 items", 3,      obj~items );

      self~assertNotSame( "Each new queue object should be unique", obj, lastObj );
      lastObj = obj;

      i = i + 1;
      iterator~next;
    end

    -- Double check the logic of the test.
    self~assertEquals( "Expected to create" count "unique queues", count, i );

    if self~class~verbose > 2 then
      say 'Creating and testing' count 'new queue objects took' time( 'R' ) 'seconds.';

  -- End test_newReptitively( )


  /* test_[]( )- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Test the .queue instance method: [].

      >>-[index]-----------------------------------------------------><

      Returns the same value as the AT method. See AT.

      The order in which the queue items appear in the array is the same as
      their queuing order, with the head of the queue as index 1.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  'test_[]';


  -- End test_[]( )

  /* test_[]=( ) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Test the .queue instance method: []=.

      >>-[index]=item------------------------------------------------><

      This method is the same as the PUT method. See PUT.

  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  'test_[]=';


  -- End test_[]=( )

  /* test_at( )- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Test the .queue instance method: at.

      >>-AT(index)---------------------------------------------------><

      Returns the item associated with index index. If the collection has no
      item associated with index, this method returns the NIL object.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  test_at;


  -- End test_at( )

  /* test_hasIndex( )- - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Test the .queue instance method: hasindex.

      >>-HASINDEX(index)---------------------------------------------><

      Returns 1 (true) if the collection contains any item associated with
      index index, or 0 (false).
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  test_hasIndex;

    if self~class~verbose > 2 then
      say '*In test_hasIndex';

    -- Test that a queue with 100 items has all indexes 1 through 100, and no
    -- more.
    q = .queue~new;
    do n over self~class~arrayOf100numbers
      q~queue( n );
    end
    do i = 1 to 100
      self~assertTrue( 'Queue must have an index of' i, q~hasindex( i ) );
    end

    self~assertFalse( 'This queue can not have an index of 101', q~hasindex( 101 ) );
    self~assertFalse( 'This queue can not have an index of 102', q~hasindex( 102 ) );

    -- Test that a relatively big integer does not cause a problem.
    self~assertFalse( 'This queue can not have an index of 999,999,999',  q~hasindex(  999999999 ) );

    /*
      This test does not work as I anticipated, it generates a syntax error
      rather than false.

    numeric digits 10;
    self~assertTrue( 'This queue can not have an index of 1,000,000,000', q~hasindex( 1000000000 ) );
    */

    /*
      Rick does not agree with my thinking that this is valid.

    -- Test that we can try any non-exisitent index, of any type.
    self~assertFalse( 'No queue can have an index of 0', q~hasindex(   0 ) );

    tbl = .table~new;
    self~assertFalse( 'No queue can have an index of' tbl, q~hasindex( tbl ) );
    */

    -- Test that hasindex is correct after the queue has been re-ordered.
    q = self~fillQueueWithBoth( .queue~new );
    do i = 199 to 0 by -11
      q~remove( i );
    end
    lastIndex = q~items;

    do i = 1 to lastIndex
      self~assertTrue( 'Queue must have an index of' i, q~hasindex( i ) );
    end
    self~assertFalse( 'Queue can not have index of' lastIndex + 1, q~hasindex( lastIndex + 1 ) );

    -- Test that hasindex is correct with an empty queue.
    q = .queue~new;
    self~assertFalse( 'Queue can not have an index of 1'                   1, q~hasindex(         1 ) );
    self~assertFalse( 'Queue can not have an index of 2'                   2, q~hasindex(         2 ) );
    self~assertFalse( 'Queue can not have an index of 999,999,999' 999999999, q~hasindex( 999999999 ) );

  -- End test_hasIndex( )

  /* test_items( ) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Test the .queue instance method: items.

      >>-ITEMS-------------------------------------------------------><

      Returns the number of items in the collection.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  test_items;

    if self~class~verbose > 2 then
      say '*In test_items';

    q = .queue~new;
    self~assertTrue( 'Empty queue should have 0 items', q~items == 0 );

    -- Queue 100 numbers, should have 100 items.
    do number over self~class~arrayOf100numbers
      q~queue( number );
    end
    self~assertTrue( 'Queued 100 times, queue should have 100 items', q~items == 100 );

    -- After each remove, ~items should be one less.
    do i = 100 to 1 by -1
      q~pull;
      self~assertEquals( "After each pull, count of items should be 1 less", i - 1, q~items );
    end

    -- Double check we are empty.
    self~assertTrue( 'Empty queue should have 0 items', q~items == 0 );

    -- Similar basic tests using objects (no reason to expect an object to be
    -- queued any different, but you never know.)
    arr = self~class~arrayOf100objects;
    do i = 1 to 100
      q~push( arr[ i ] );
      self~assertEquals( 'Items should equal count of pushes', i, q~items );
    end

    -- Remove every other object in queue, expect count of items to be correct
    -- after the queue adjusts its indexes.
    j = 100;
    do i = 100 to 1 by -2
      q~remove( i );
      j = j - 1;
      self~assertEquals( 'After each remove, count of items should be 1 less', j, q~items );
    end

    -- Double check my counting.
    self~assertEquals( 'Queue should have 50 items', 50, q~items );

    -- Same thing, remove every 5th object in the queue.
    j = 50;
    do i = 50 to 1 by -5
      q~remove( i );
      j = j - 1;
      self~assertEquals( 'After each remove, count of items should be 1 less', j, q~items );
    end
    self~assertEquals( 'Queue should have 40 items', 40, q~items );

    -- Use ~items in a do statement.
    do q~items
      q~pull;
    end
    self~assertTrue( 'Queue should be empty', q~items == 0 );

    -- Pull from an empty queue a number of times and see that items remains 0.
    do 50
      q~pull;
    end
    self~assertTrue( 'Queue should be empty', q~items == 0 );

    -- Try a relatively large number of items.
    do 1000
      do n over self~class~arrayOf100numbers;
        q~queue( n );
      end
      do o over self~class~arrayOf100objects;
        q~push( o );
      end
    end
    self~assertEquals( 'Queue should have 200,000 items', 200000, q~items );

    -- Remove a couple of miscellaneous items from the queue, (which forces
    -- the queue to readjust a lot of indexes,) and check the item count.
    q~~remove( 3  )~~remove( 11 )~~remove( 19 );
    self~assertEquals( 'Queue should have 199,997 items', 199997, q~items );

    -- Remove all but 1 item and check count.
    do 199996
      q~pull;
    end
    self~assertEquals( 'Queue should have 1 item', 1, q~items );

  -- End test_items( )

  /* test_makearray( ) - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Test the .queue instance method: makearray.

      >>-MAKEARRAY---------------------------------------------------><

      Returns a single-index array containing the receiver queue items. The
      array indexes range from 1 to the number of items. The order in which the
      queue items appear in the array is the same as their queuing order, with
      the head of the queue as index 1.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  test_makearray;


  -- End test_makearray( )

  /* test_peek( )- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Test the .queue instance method: peek.

      >>-PEEK--------------------------------------------------------><

      Returns the item at the head of the queue. The collection remains
      unchanged.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  test_peek;

    q   = .queue~new
    obj = q~peek;
    self~assertNull( 'Peek on empty queue should return .nil', obj );

  -- End test_peek( )


  /* test_pull( )- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Test the .queue instance method: pull.

      >>-PULL--------------------------------------------------------><

      Returns and removes the item at the head of the queue.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  test_pull;

    -- Test on an empty queue.
    q   = .queue~new
    obj = q~pull;
    self~assertNull( 'Pull from empty queue should return .nil', obj );


  -- End test_pull( )

  /* test_push( )- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Test the .queue instance method: push.

      >>-PUSH(item)--------------------------------------------------><

      Adds the object item to the head of the queue.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  test_push;


  -- End test_push( )

  /* test_put( ) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Test the .queue instance method: put.

      >>-PUT(item,index)---------------------------------------------><

      Replaces any existing item associated with the specified index with the
      new item. If the index does not exist in the queue, an error is raised.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  test_put;


  -- End test_put( )

  /* test_queue( ) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Test the .queue instance method: queue
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  test_queue;

    if self~class~verbose > 2 then
      say '*In test_queue';

    -- Test that we can queue simple numbers ...
    q = .queue~new;
    do n over self~class~arrayOf100numbers;
      q~queue( n );
    end
    self~assertEquals( 'Queued 100 times, should have 100 items', 100, q~items );

    -- ... and test we can queue objects.
    q = .queue~new
    do o over self~class~arrayOf100objects;
      q~queue( o );
    end
    self~assertEquals( 'Queued 100 times, should have 100 items', 100, q~items );

    -- Test we can queue the .nil object ...
    q = .queue~new
    do 100
      q~queue( .nil );
    end
    self~assertEquals( 'Queued 100 times, should have 100 items', 100, q~items );

    -- ... and test each queued object is the .nil object.
    do obj over q
      self~assertEquals( 'Each object in queue should be the .nil object', .nil, obj );
    end

    -- Test that we can queue a queue.
    q = .queue~new
    testQ = .queue~new~~queue( 'one' )~~queue( 'two' )~~queue( 'three' );
    do 100
      q~queue( testQ );
    end
    self~assertEquals( 'Queued 100 times, should have 100 items', 100, q~items );
    do obj over q
      self~assertEquals( 'Each object in queue should be the test queue', testQ, obj );
    end

    -- Test that we can queue a class object.
    q = .queue~new;
    do 100
      q~queue( .method );
    end
    self~assertEquals( 'Queued 100 times, should have 100 items', 100, q~items );
    do obj over q
      self~assertEquals( 'Each object in queue should be the .method class object', .method, obj );
    end

    -- Test that each queued item is queued to the tail of the queue.
    q = .queue~new;
    do n over self~class~arrayOf100numbers;
      q~queue( n );
      self~assertEquals( 'Each queued object should be at the tail', n, q[ q~items ] );
    end
    do o over self~class~arrayOf100objects;
      q~queue( o );
      self~assertEquals( 'Each queued object should be at the tail', o, q[ q~items ] );
    end

    -- Test each queued item has the correct index.  (Doubt that this proves
    -- much the last test did not prove.)
    q = .queue~new;
    do n over self~class~arrayOf100numbers;
      q~queue( n );
    end
    do o over self~class~arrayOf100objects;
      q~queue( o );
    end

    n = self~class~arrayOf100numbers;
    do i = 1 to 100
      self~assertEquals( 'Queue object at index should match object at array index', n[ i ], q[ i ] );
    end
    o = self~class~arrayOf100objects;
    do i = 101 to 200
      self~assertEquals( 'Queue object at index should match object at array index', o[ i - 100 ], q[ i ] );
    end

    -- Test that we can queue a relatively large number of times.
    q = .queue~new;
    do 1000
      do n over self~class~arrayOf100numbers;
        q~queue( n );
      end
      do o over self~class~arrayOf100objects;
        q~queue( o );
      end
    end
    self~assertEquals( 'Queue should have 200,000 items', 200000, q~items );

  -- End test_queue( )

  /* test_supplier( )- - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Test the .queue instance method: supplier.

      >>-SUPPLIER----------------------------------------------------><

      Returns a supplier object for the collection. After you have obtained a
      supplier, you can send it messages (see The Supplier Class) to enumerate
      all the items that were in the queue at the time of the supplier’s
      creation. The supplier enumerates the items in their queuing order, with
      the head of the queue first.

  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  test_supplier;

    -- Test that the supplier method returns a supplier.
    q = .queue~new;
    q~queue( 1 );
    obj = q~supplier
    self~assertEquals( 'Supplier method should return a supplier object (1)', .supplier, obj~class );

    -- Test the returned supplier is correct.
    self~assertEquals( 'Supplier index must be 1', 1, obj~index );
    self~assertEquals( 'Supplier item must be 1',  1, obj~item  );
    count = 0;
    do while obj~available
      count = count + 1;
      obj~next;
    end
    self~assertEquals( 'Supplier must have exactly 1 index/item', 1, count );

    -- Test that an empty queue produces an empty supplier.
    q     = .queue~new;
    obj   = q~supplier;
    count = 0;
    self~assertEquals( 'Supplier method should return a supplier object (2)', .supplier, obj~class );
    do while obj~available
      count = count + 1;
      obj~next;
    end
    self~assertEquals( 'Supplier must not have any index/item', 0, count );

    -- Test that the supplier is correct with a queue having a number of
    -- elements; that the supplier produces each and every item in the queue
    -- and nothing else.
    q = self~fillQueueWithBoth( .queue~new );

    holder = .set~new;
    do n over self~class~arrayOf100numbers
      holder~put( n );
    end
    do o over self~class~arrayOf100objects
      holder~put( o );
    end

    -- Save a copy of the holder for another test.
    holderSafe = holder~copy;

    obj   = q~supplier;
    count = 0;
    self~assertEquals( 'Supplier method should return a supplier object (3)', .supplier, obj~class );
    do while obj~available
      count = count + 1;
      self~assertTrue( 'Supplier item ('obj~item') must be in the holder set (1)', holder~hasindex( obj~item ) );
      holder~remove( obj~item );
      obj~next;
    end
    self~assertEquals( 'Supplier must have exactly 200 indexes/items (1)',   0, holder~items );
    self~assertEquals( 'Supplier must have exactly 200 indexes/items (2)', 200,        count );

    -- Test that we get the same, correct supplier back if we repeat the method
    -- call.
    holder = holderSafe;
    obj    = q~supplier;
    count  = 0;
    self~assertEquals( 'Supplier method should return a supplier object (4)', .supplier, obj~class );
    do while obj~available
      count = count + 1;
      self~assertTrue( 'Supplier item ('obj~item') must be in the holder set (2)', holder~hasindex( obj~item ) );
      holder~remove( obj~item );
      obj~next;
    end
    self~assertEquals( 'Supplier must have exactly 200 indexes/items (3)',   0, holder~items );
    self~assertEquals( 'Supplier must have exactly 200 indexes/items (4)', 200,        count );

    -- Test that the supplier is correct after the queue has been re-ordered.
    do i = 200 to 0 by -7
      q~remove( i );
    end
    total = q~items;

    do i = 1 to q~items
      holder~put( q~at( i ) );
    end

    obj   = q~supplier;
    count = 0;
    self~assertEquals( 'Supplier method should return a supplier object (5)', .supplier, obj~class );
    do while obj~available
      count = count + 1;
      self~assertTrue( 'Supplier item ('obj~item') must be in the holder set (2)', holder~hasindex( obj~item ) );
      holder~remove( obj~item );
      obj~next;
    end
    self~assertEquals( 'Supplier must have exactly' total 'indexes/items (1)',     0, holder~items );
    self~assertEquals( 'Supplier must have exactly' total 'indexes/items (2)', total,        count );

  -- End test_supplier( )

  -- Attribute: arrayOf100objects
  --   An array to hold 100 objects.  This array is not changed by any test once
  --   it has been created, so it only needs to be initialized one time.
  ::method  arrayOf100objects attribute class;

  -- Attribute: arrayOf100numbers
  --   Holds the numbers 1 through 100.  Like arrayOf100objects, this array is
  --   not changed by any test cases and only needs to be initialized once.
  ::method  arrayOf100numbers attribute class;

  /* setUp( ) - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
      Some initialization to be performed prior to each test running.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  setUp;

    -- Array only needs to be created and filled one time.  No test changes the
    -- array in any way.
    if self~class~arrayOf100numbers~class <> .array then do
      arr = .array~new;
      do i = 1 to 100
        arr[ i ] = i;
      end
      self~class~arrayOf100numbers = arr;
    end

    -- Likewise, no test changes this array.  Note, no item in this array can
    -- match an item in the arrayOf100numbers array.  Do not do: arr[ i ] = i
    if self~class~arrayOf100objects~class <> .array then do
      arr = .array~of( 'one', 'two', 'three', 'four', 'five' );
      do i = 6 to 100
        select
          when (i // 5) == 0 then
            arr[ i ] = .directory~new~~setentry( i, i );

          when (i // 4) == 0 then
            arr[ i ] = .table~new~~put( i, "tableIndex"i );

          when (i // 3) == 0 then
            arr[ i ] = .set~of( i );

          when (i // 2) == 0 then
            arr[ i ] = .list~of( i );

          otherwise
            arr[ i ] = .bag~of( i );

        end
        -- End select
      end
      -- End do i = 6 to 100

      self~class~arrayOf100objects = arr;

      if self~class~verbose > 9 then
        self~printObjectArray;
    end
    -- End if self~class~arrayOf100objects~class <> .array

  -- End setUp( )

  /* fillQueueWithNumbers( q ) - - - - - - - - - - - - - - - - - - - - - - - -*\

    Adds all the numbers in the arrayOf100numbers array to the specified queue.
    The numbers are added to the end of the queue.

    Input:
      q  REQUIRED
        The queue in which to add the numbers.

    Returns:
      The queue object.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  fillQueueWithNumbers private;
    use arg q;

    -- Might as well take advantage of our assert facility.
    self~assertEquals( 'Arg to fillQueueWithNumbers() method must be a queue', .queue, q~class );
    do number over self~class~arrayOf100numbers
      q~queue( number );
    end

  return q;
  -- End fillQueueWithNumbers( q )

  /* fillQueueWithObjects( q ) - - - - - - - - - - - - - - - - - - - - - - - -*\

    Adds all the objects in the arrayOf100objects array to the specified queue.
    The objects are added to the end of the queue.

    Input:
      q  REQUIRED
        The queue in which to add the objects.

    Returns:
      The queue object.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  fillQueueWithObjects private;
    use arg q;

    -- Might as well take advantage of our assert facility.
    self~assertEquals( 'Arg to fillQueueWithObjects() method must be a queue', .queue, q~class );
    do obj over self~class~arrayOf100objects
      q~queue( obj );
    end

  return q;
  -- End fillQueueWithObjects( q )

  /* fillQueueWithBoth( q )- - - - - - - - - - - - - - - - - - - - - - - - - -*\

    Adds all the numbers in the arrayOf100numbers array and all the objects in
    arrayOf100objects to the specified queue.  The numbers are added first then
    the objects.  Everything is added to the end of the queue.

    Input:
      q  REQUIRED
        The queue to work with.

    Returns:
      The queue object.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  fillQueueWithBoth private;
    use arg q;

    -- Might as well take advantage of our assert facility.
    self~assertEquals( 'Arg to fillQueueWithBoth() method must be a queue', .queue, q~class );
    self~fillQueueWithNumbers( q );
    self~fillQueueWithObjects( q );

  return q;
  -- End fillQueueWithBoth( q )

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
  Code below this separator is useful during the implementation of this test
  unit.  It has helped with debugging the test unit itself.  It could be removed
  when the test unit is fully implemented.
\* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  -- Attribute-like: verbose                 public / private
  --   Flag used while implementing this test unit.  Controls if extra messages
  --   are printed to the console while this test unit is executed.  Turn on
  --   by calling this program file using an arg of exactly 'verboseN', where
  --   N is an integer from 1 to 10.   Anything else turns the extra messages
  --   off.  The higher N, the more verbose.
  ::method  verbose class;
    expose verbose;
  return verbose;

  ::method  'verbose=' class private;
    expose verbose;
  use arg verbose;
  -- End verbose( )

  /* init( ) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\

    Class method to initialize some class variables.

    Input:
      None.

    Returns:
      0, always.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  init class;
    use arg;
    self~verbose = 0;
    forward class (super);
  return 0;
  -- End init( )

  /* setVerbose( flag )- - - - - - - - - - - - - - - - - - - - - - - - - - - -*\

    Sets the verbose class attribute as specified.

    Input:
      flag  OPTIONAL
        If this is exactly: 'verboseN' where N is an integer from 1 to 10 then
        verbose is set to the value of N.  Anything else, including omitting the
        argument sets verbose off.

    Returns:
      The state of the verbose setting after this method executes.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  setVerbose class;
    use arg flag;

    if flag~class == .string then do
      if flag~abbrev( 'verbose' ) then do
        N = flag~substr( 8 );
        if N~datatype( 'W' ) then do
          if N > 0 & N < 11 then do
            self~verbose = N;
          end
        end
      end
    end

  return self~verbose;
  -- End setVerbose( flag )

  /* printObjectArray( ) - - - - - - - - - - - - - - - - - - - - - - - - - - -*\

    A convenience method to print out the arrayOf100objects array.  Used to help
    with the implementation of this test unit.

    Input:
      None.

    Returns:
      0, always.
  \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  ::method  printObjectArray private;
    use arg;

    if self~class~arrayOf100objects~class == .array then do
      do obj over self~class~arrayOf100objects
        itr = .nil;

        select
          when obj~class == .string then do
            say 'Got a string.';
            say '  Value:' obj;
          end

          when obj~class == .table then do
            say 'Got a table.';
            itr = obj~supplier;
          end

          when obj~class == .set then do
            say 'Got a set.';
            itr = obj~supplier;
          end

          when obj~class == .bag then do
            say 'Got a bag.';
            itr = obj~supplier;
          end

          when obj~class == .list then do
            say 'Got a list.';
            itr = obj~supplier;
          end

          when obj~class == .directory then do
            say 'Got a directory.';
            itr = obj~supplier;
          end

          otherwise do
            say 'This is an error, object is not as expected!';
            say '  Object class:' obj~class;
          end
        end
        -- End select

        if itr <> .nil then do while itr~available
            say '  Index:' itr~index;
            say '  Item: ' itr~item;
            itr~next;
          end
        end
        say;
    end

  return 0;
  -- End printObjectArray( )

-- End of class: ooRexx.Base.Class.Queue.TestUnit