view gcc/testsuite/ada/acats/tests/c9/c940013.a @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children
line wrap: on
line source

-- C940013.A
--
--                             Grant of Unlimited Rights
--
--     Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
--     F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained 
--     unlimited rights in the software and documentation contained herein.
--     Unlimited rights are defined in DFAR 252.227-7013(a)(19).  By making 
--     this public release, the Government intends to confer upon all 
--     recipients unlimited rights  equal to those held by the Government.  
--     These rights include rights to use, duplicate, release or disclose the 
--     released technical data and computer software in whole or in part, in 
--     any manner and for any purpose whatsoever, and to have or permit others 
--     to do so.
--
--                                    DISCLAIMER
--
--     ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
--     DISCLOSED ARE AS IS.  THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED 
--     WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
--     SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE 
--     OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
--     PARTICULAR PURPOSE OF SAID MATERIAL.
--*
--
-- OBJECTIVE: 
--      Check that items queued on a protected entry are handled FIFO and that
--      the  'count attribute of that entry reflects the length of the queue.
-- 
-- TEST DESCRIPTION:
--      Use a small subset of the freeway ramp simulation shown in other
--      tests.  With the timing pulse off (which prevents items from being
--      removed from the queue) queue up a small number of calls.  Start the
--      timing pulse and, at the first execution of the entry code, check the
--      'count attribute. Empty the queue.   Pass the items being removed from
--      the queue to the Ramp_Sensor_01 task; there check that the items are
--      arriving in FIFO order.  Check the final 'count value  
--      
--      Send another batch of items at a rate which will, if the delay timing
--      of the implementation is reasonable, cause the queue length to
--      fluctuate in both directions.   Again check that all items arrive
--      FIFO.  At the end check that the 'count returned to zero reflecting
--      the empty queue.  
--      
--
-- CHANGE HISTORY:
--      06 Dec 94   SAIC    ACVC 2.0
--
--!

with Report;
with ImpDef;
with Ada.Calendar;
                
procedure C940013 is

   TC_Failed_1 : Boolean := false;

begin

   Report.Test ("C940013", "Check that queues on protected entries are " &
                           "handled FIFO and that 'count is correct");

   declare  -- encapsulate the test

      function "+" (Left : Ada.Calendar.Time; Right: Duration)
                            return Ada.Calendar.Time renames Ada.Calendar."+";

      -- Weighted load given to each potential problem area and accumulated
      type Load_Factor is range 0..8;
      Clear_Level    : constant Load_Factor := 0;
      Minimum_Level  : constant Load_Factor := 1;
      Moderate_Level : constant Load_Factor := 2;
      Serious_Level  : constant Load_Factor := 4;
      Critical_Level : constant Load_Factor := 6;

      TC_Expected_Passage_Total : constant integer := 624;

      -- For this test give each vehicle an integer ID incremented
      -- by one for each successive vehicle.  In reality this would be
      -- a more complex alpha-numeric ID assigned at pickup time.
      type Vehicle_ID is range 1..5000;
      Next_ID : Vehicle_ID := Vehicle_ID'first;  

      -- In reality this would be about 5 seconds. The default value of 
      -- this constant in the implementation defined package is similar
      -- but could, of course be considerably different - it would not 
      -- affect the test 
      -- 
      Pulse_Time_Delta : duration := ImpDef.Clear_Ready_Queue;


      task Pulse_Task;       -- task to generate a pulse for each ramp

      -- Carrier task. One is created for each vehicle arriving at the ramp
      task type Vehicle is
         entry Get_ID (Input_ID : in Vehicle_ID);
      end Vehicle;      
      type acc_Vehicle is access Vehicle;

      task Ramp_Sensor_01 is
         entry  Accept_Vehicle (Input_ID : in Vehicle_ID);
         entry  TC_First_Three_Handled;
         entry  TC_All_Done;
      end Ramp_Sensor_01;

      protected Pulse_State is 
         procedure Start_Pulse;
         procedure Stop_Pulse;
         function Pulsing return Boolean;
      private
         State : Boolean := false;   -- start test will pulse off
      end Pulse_State;

      protected body Pulse_State is 

         procedure Start_Pulse is
         begin
            State := true;
         end Start_Pulse;

         procedure Stop_Pulse is
         begin 
            State := false;
         end Stop_Pulse;

         function Pulsing return Boolean is
         begin 
            return State;
         end Pulsing;
     
      end Pulse_State;

      --================================================================
      protected Test_Ramp is 
      
         function Meter_in_use_State    return Boolean; 
         procedure Time_Pulse_Received;
         entry Wait_at_Meter;
         procedure TC_Passage (Pass_Point : Integer);
         function TC_Get_Passage_Total return integer;
         function TC_Get_Count return integer;
   
      private

         Release_One_Vehicle : Boolean := false;
         -- For this test have Meter_in_Use already set
         Meter_in_Use        : Boolean := true;

         TC_Wait_at_Meter_First : Boolean := true;
         TC_Entry_Queue_Count   : integer := 0; -- 'count of Wait_at_Meter
         TC_Passage_Total       : integer := 0;
         TC_Pass_Point_WAM      : integer := 23;

      end Test_Ramp;  
      --================================================================
      protected body Test_Ramp is
   
         -- External call for Meter_in_Use
         function Meter_in_Use_State return Boolean is
         begin
            return Meter_in_Use;
         end Meter_in_Use_State;
   
         -- Trace the paths through the various routines by totalling the
         -- weighted call parameters
         procedure TC_Passage (Pass_Point : Integer) is
         begin
            TC_Passage_Total := TC_Passage_Total + Pass_Point;
         end TC_Passage;
   
         -- For the final check of the whole test
         function TC_Get_Passage_Total return integer is
         begin
            return TC_Passage_Total;
         end TC_Get_Passage_Total;
   
         function TC_Get_Count return integer is
         begin
            return TC_Entry_Queue_Count;
         end TC_Get_Count;
   

         -- Here each Vehicle task queues itself awaiting release
         --
         entry Wait_at_Meter when Release_One_Vehicle is
         -- EXAMPLE OF ENTRY WITH BARRIERS AND PERSISTENT SIGNAL
         begin
            --
            TC_Passage ( TC_Pass_Point_WAM );   -- note passage
            -- For this test three vehicles are queued before the first
            -- is released.  If the queueing mechanism is working correctly
            -- the first time we pass through here the entry'count should
            -- reflect this
            if TC_Wait_at_Meter_First then
               if Wait_at_Meter'count /= 2 then
                  TC_Failed_1 := true;
               end if;
               TC_Wait_at_Meter_First := false;
            end if;
            TC_Entry_Queue_Count := Wait_at_Meter'count;  -- note for later
               
            Release_One_Vehicle := false;   -- Consume the signal
            null; -- stub ::: Decrement count of number of vehicles on ramp 
         end Wait_at_Meter;      

   
         procedure Time_Pulse_Received is
            Load : Load_factor := Minimum_Level;   -- for this version of the 
            Freeway_Breakdown : Boolean := false;  -- test, freeway is Minimum
         begin
            -- if broken down, no vehicles are released
            if not Freeway_Breakdown then 
               if Load < Moderate_Level then
                  Release_One_Vehicle := true;
               end if;
               null;    -- stub  ::: If other levels, release every other
                        --           pulse, every third pulse  etc.
            end if;
         end Time_Pulse_Received;
       
      end Test_Ramp;  
      --================================================================

      -- Simulate the arrival of a vehicle at the Ramp_Receiver and the
      -- generation of an accompanying carrier task
      procedure New_Arrival is
         Next_Vehicle_Task: acc_Vehicle := new Vehicle;
         TC_Pass_Point : constant integer := 3; 
      begin
         Next_ID := Next_ID + 1;
         Next_Vehicle_Task.Get_ID(Next_ID);
         Test_Ramp.TC_Passage ( TC_Pass_Point );  -- Note passage through here
         null;
      end New_arrival;


      -- Carrier task. One is created for each vehicle arriving at the ramp
      task body Vehicle is
         This_ID : Vehicle_ID;
         TC_Pass_Point_2 : constant integer := 21;
      begin
         accept Get_ID (Input_ID : in Vehicle_ID) do 
            This_ID := Input_ID;
         end Get_ID;

         if Test_Ramp.Meter_in_Use_State then  
            Test_Ramp.TC_Passage ( TC_Pass_Point_2 );  -- note passage
            null;  -- stub::: Increment count of number of vehicles on ramp 
            Test_Ramp.Wait_at_Meter;      -- Queue on the meter entry
         end if;

         -- Call to the first in the series of the Ramp_Sensors
         --     this "passes" the vehicle from one sensor to the next
         --     Each sensor will requeue the call to the next thus this
         --     rendezvous will only be completed as the vehicle is released
         --     by the last sensor on the ramp.
         Ramp_Sensor_01.Accept_Vehicle (This_ID);
      exception
         when others => 
               Report.Failed ("Unexpected exception in Vehicle Task");
      end Vehicle;

      task body Ramp_Sensor_01 is
         TC_Pass_Point : constant integer := 31; 
         This_ID    : Vehicle_ID;
         TC_Last_ID : Vehicle_ID := Vehicle_ID'first;
      begin
         loop
            select
               accept Accept_Vehicle (Input_ID : in Vehicle_ID) do 
                  null;   -- stub:::: match up with next Real-Time notification
                          -- from the sensor.  Requeue to next ramp sensor
                  This_ID := Input_ID;
                  
                  -- The following is all Test_Control code
                  Test_Ramp.TC_Passage ( TC_Pass_Point );  -- note passage
                  -- The items arrive in the order they are taken from
                  -- the Wait_at_Meter entry queue
                  if ( This_ID - TC_Last_ID ) /= 1 then
                     -- The tasks are being queued (or unqueued) in the
                     -- wrong order
                     Report.Failed
                              ("Queueing on the Wait_at_Meter queue failed");
                  end if;
                  TC_Last_ID := This_ID;    -- for the next check
                  if TC_Last_ID = 4 then
                     -- rendezvous with the test driver
                     accept TC_First_Three_Handled;
                  elsif TC_Last_ID = 9 then
                     -- rendezvous with the test driver
                     accept TC_All_Done;
                  end if;
               end Accept_Vehicle;
            or
               terminate;
            end select;
         end loop;
      exception
         when others => 
               Report.Failed ("Unexpected exception in Ramp_Sensor_01");
      end Ramp_Sensor_01;


      -- Task transmits a synchronizing "pulse" to all ramps
      --
      task body Pulse_Task is
         Pulse_Time : Ada.Calendar.Time;
      begin
         While not Pulse_State.Pulsing loop
            -- Starts up in the quiescent state
            delay ImpDef.Minimum_Task_Switch; 
         end loop;
         Pulse_Time := Ada.Calendar.Clock;
         While Pulse_State.Pulsing loop
            delay until Pulse_Time;  
            Test_Ramp. Time_Pulse_Received;   -- Transmit pulse to test_ramp
            -- ::::::::::  and to all the other ramps
            Pulse_Time := Pulse_Time + Pulse_Time_Delta; -- calculate next
         end loop;
      exception
         when others => 
               Report.Failed ("Unexpected exception in Pulse_Task");
      end Pulse_Task;


   begin -- declare

      -- Test driver.  This is ALL test control code

      -- Arrange to queue three vehicles on the Wait_at_Meter queue.  The 
      -- timing pulse is quiescent so the queue will build
      for i in 1..3 loop
         New_Arrival; 
      end loop;

      delay Pulse_Time_Delta;  -- ensure all is settled

      Pulse_State.Start_Pulse;     -- Start the timing pulse, the queue will 
                                   -- be serviced
      
      -- wait here until the first three are complete
      Ramp_Sensor_01.TC_First_Three_Handled;

      if Test_Ramp.TC_Get_Count /= 0 then
         Report.Failed ("Intermediate Wait_at_Entry'count is incorrect");
      end if;

      -- generate new arrivals at a rate that will make the queue increase
      -- and decrease "randomly"
      for i in 1..5 loop
         New_Arrival; 
         delay Pulse_Time_Delta/2;
      end loop;

      -- wait here till all have been handled
      Ramp_Sensor_01.TC_All_Done;

      if Test_Ramp.TC_Get_Count /= 0 then
         Report.Failed ("Final Wait_at_Entry'count is incorrect");
      end if;

      Pulse_State.Stop_Pulse;       -- finish test


      if TC_Expected_Passage_Total /= Test_Ramp.TC_Get_Passage_Total then
         Report.Failed ("Unexpected paths taken");
      end if;


   end; -- declare

   if TC_Failed_1 then 
      Report.Failed ("Wait_at_Meter'count incorrect");
   end if;

   Report.Result;

end C940013;