(*

    Stack Array library testing program.

    by: Ilya Shlyakhter
*)


PROGRAM TestStackArray (Input,Output);

   USES StackAry, RandLib;

   PROCEDURE GreetTheUser;

      BEGIN  (* GreetTheUser *)
         WriteLn;
         Write ('       *** STARTING THE TEST ***');
         WriteLn;
	 WriteLn
      END;   (* GreetTheUser *)

   PROCEDURE RandomStackData (VAR Data: StackDataType);

   (*
      NOTE: I've tried to make this library as portable and generic as possible.
      However, the way you generate random data heavily depends on the type of
      data.  Therefore, if the data type used in this program is modified, this
      procedure and the next one also have to be modified.
   *)

      VAR R: Real;

      BEGIN  (* RandomStackData *)
         R := RandomGarlandReal;

         IF R >= 0.5 THEN
            Data := Chr (RandomGarlandInt (Ord ('A'), Ord ('Z')))  (* capital letter *)
               ELSE
                  Data := Chr (RandomGarlandInt (Ord ('a'), Ord ('z')))  (* small letter *)
      END;   (* RandomStackData *)


   PROCEDURE DisplayData (TheData: StackDataType);

   (*
      NOTE: See comment for the previous procedure.
   *)

      BEGIN  (* DisplayData *)
         Write (TheData)
      END;   (* DisplayData *)

   PROCEDURE TestHello;

      VAR Stack: StackType;
          Ch: StackDataType;
          Error: Boolean;

      BEGIN  (* TestHello *)
         InitStack (Stack);

         WriteLn ('Pushing the word HELLO onto the stack:');

         Push (Stack,'H',Error);
         Push (Stack,'E',Error);
         Push (Stack,'L',Error);
         Push (Stack,'L',Error);
         Push (Stack,'O',Error);

         WriteLn;
         WriteLn ('The stack now contains ',GetStackSize (Stack),' elements.');
         Peek (Stack,Ch,Error);
         Write ('The element at the top is ');
         DisplayData (Ch);
         WriteLn;

         WriteLn ('The stack now contains the following elements: ');
         WriteLn;

         Pop (Stack,Ch,Error);
         WHILE NOT Error DO
            BEGIN  (* write out the elements of the stack *)
               DisplayData (Ch);
               Pop (Stack,Ch,Error);
            END;   (* write out the elements of the stack *)

         WriteLn;
         WriteLn ('    --- End of Hello Test ---');
         WriteLn
      END;   (* TestHello *)

   PROCEDURE TestNumbers;

      CONST CharsPerLine = 25;

      VAR I: StackIndexType;
          TestStack: StackType;
          Ch: StackDataType;
          Error: Boolean;
          OutCount: Integer;  (* number of character output on the line *)

      BEGIN  (* TestNumbers *)
         InitGarland (ClockSeedInt);
         InitStack (TestStack);

         WriteLn;
         WriteLn;
         WriteLn ('Pushing the following data elements onto the stack:');
         WriteLn;

         OutCount := 1;

         FOR I := 1 TO MaxStackSize DO
            BEGIN  (* push a random element on the stack *)
               RandomStackData (Ch);
               DisplayData (Ch);
               Push (TestStack, Ch, Error);

               IF OutCount = CharsPerLine THEN
                  BEGIN  (* new line *)
                     OutCount := 1;
                     WriteLn
                  END    (* new line *)
                     ELSE
                        OutCount := OutCount + 1
            END;   (* push a random element on the stack *)

         WriteLn;
         WriteLn ('The size of the stack is now ',GetStackSize (TestStack),'.');
         Write ('The item at the top of the stack is: ');
         Peek (TestStack, Ch, Error);
         DisplayData (Ch);
         WriteLn;

         WriteLn;
         WriteLn ('Retrieving elements from the stack:');
         WriteLn;

         OutCount := 1;
         Pop (TestStack, Ch, Error);
         WHILE NOT Error DO
            BEGIN  (* show stack *)
               DisplayData (Ch);
               IF OutCount = CharsPerLine THEN
                  BEGIN  (* new line *)
                     WriteLn;
                     OutCount := 1
                  END    (* new line *)
                     ELSE
                        OutCount := OutCount + 1;

               Pop (TestStack, Ch, Error)
            END;    (* show stack *)
         WriteLn;
         WriteLn ('    --- End Of Stack ---');
         WriteLn
      END;   (* TestNumbers *)

   PROCEDURE TestRobustness;

      VAR TestStack: StackType;
          Ch: StackDataType;
          Error: Boolean;
          I: Integer;  (* NOTE: the type of this variable must be changed *)
                       (*       if the type StackIndexType is changed.    *)


      BEGIN  (* TestRobustness *)
         WriteLn;
         WriteLn ('    --- Starting Robustness Test ---');
         WriteLn;
         InitStack (TestStack);

         Write ('Peeking into an empty stack: ');
         Peek (TestStack, Ch, Error);
         WriteLn ('Error = ', Error);

         Write ('Reading from an empty stack: ');
         Pop (TestStack, Ch, Error);
         WriteLn ('Error = ',Error);

         Write ('Pushing an element onto the stack: ');
         RandomStackData (Ch);
         Push (TestStack, Ch, Error);
         WriteLn ('Error = ',Error);

         Write ('Peeking onto a good stack: ');
         Peek (TestStack, Ch, Error);
         WriteLn ('Error = ',Error);

         Write ('Retrieving an element from a good stack: ');
         Pop (TestStack, Ch, Error);
         WriteLn ('Error = ',Error);

         FOR I := 1 TO MaxStackSize DO
            BEGIN  (* push a random element *)
               RandomStackData (Ch);
               Push (TestStack,Ch,Error)
            END;   (* push a random element *)

         Write ('Trying to overflow the stack: ');
         Push (TestStack,Ch,Error);
         WriteLn ('Error = ',Error);

         Write ('Peeking onto a full stack: ');
         Peek (TestStack, Ch, Error);
         WriteLn ('Error = ',Error);

         Write ('Retrieving an element from a full stack: ');
         Pop (TestStack, Ch, Error);
         WriteLn ('Error = ',Error);

         WriteLn;
         WriteLn ('    --- End of Robustness Test');
         WriteLn
      END;   (* TestRobustness *)

   PROCEDURE SayGoodBye;

      BEGIN  (* SayGoodBye *)
         WriteLn;
         WriteLn ('             *** END OF PROGRAM ***');
         WriteLn
      END;   (* SayGoodBye *)

   BEGIN  (* TestStackArray *)
      GreetTheUser;
      TestHello;
      TestNumbers;
      TestRobustness;
      SayGoodBye
   END.   (* TestStackArray *)
