2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / gcc / testsuite / ada / acats / tests / c9 / c954019.a
blobfafc6aa591fbc57f8c227767788cba847c4f18af
1 -- C954019.A
2 --
3 -- Grant of Unlimited Rights
4 --
5 -- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
6 -- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
7 -- unlimited rights in the software and documentation contained herein.
8 -- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
9 -- this public release, the Government intends to confer upon all
10 -- recipients unlimited rights equal to those held by the Government.
11 -- These rights include rights to use, duplicate, release or disclose the
12 -- released technical data and computer software in whole or in part, in
13 -- any manner and for any purpose whatsoever, and to have or permit others
14 -- to do so.
16 -- DISCLAIMER
18 -- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
19 -- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
20 -- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
21 -- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
22 -- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
23 -- PARTICULAR PURPOSE OF SAID MATERIAL.
24 --*
26 -- OBJECTIVE:
27 -- Check that when a requeue is to the same entry the items go to the
28 -- right queue and that they are placed back on the end of the queue.
30 -- TEST DESCRIPTION:
31 -- Simulate part of a message handling application where the messages are
32 -- composed of several segments. The sequence of the segments within the
33 -- message is specified by Seg_Sequence_No. The segments are handled by
34 -- different tasks and finally forwarded to an output driver. The
35 -- segments can arrive in any order but must be assembled into the proper
36 -- sequence for final output. There is a Sequencer task interposed
37 -- before the Driver. This takes the segments of the message off the
38 -- Ordering_Queue and those that are in the right order it sends on to
39 -- the driver; those that are out of order it places back on the end of
40 -- the queue.
42 -- The test just simulates the arrival of the segments at the Sequencer.
43 -- The task generating the segments handshakes with the Sequencer during
44 -- the "Await Arrival" phase ensuring that the three segments of a
45 -- message arrive in REVERSE order (the End-of-Message segment arrives
46 -- first and the Header last). In the first cycle the sequencer pulls
47 -- segments off the queue and puts them back on the end till it
48 -- encounters the header. It checks the sequence of the ones it pulls
49 -- off in case the segments are being put back on in the wrong part of
50 -- the queue. Having cycled once through it no longer verifies the
51 -- sequence - it just executes the "application" code for the correct
52 -- order for dispatch to the driver.
53 --
54 -- In this simple example no attempt is made to address segments of
55 -- another message arriving or any other error conditions (such as
56 -- missing segments, timing etc.)
59 -- CHANGE HISTORY:
60 -- 06 Dec 94 SAIC ACVC 2.0
61 -- 19 Dec 94 SAIC Remove parameter from requeue statement
63 --!
65 with Report;
66 with ImpDef;
68 procedure C954019 is
69 begin
72 Report.Test ("C954019", "Check Requeue to the same Accept");
74 declare -- encapsulate the test
76 type Segment_Sequence is range 1..8;
77 Header : constant Segment_Sequence := Segment_Sequence'first;
79 type Message_Segment is record
80 ID : integer; -- Message ID
81 Seg_Sequence_No : Segment_Sequence; -- Within the message
82 Alpha : string (1..128);
83 EOM : Boolean := false; -- true for final msg segment
84 end record;
85 type acc_Message_Segment is access Message_Segment;
87 task TC_Simulate_Arrival;
89 task type Carrier_Task is
90 entry Input ( Segment : acc_Message_Segment );
91 end Carrier_Task;
92 type acc_Carrier_Task is access Carrier_Task;
94 task Sequencer is
95 entry Ordering_Queue ( Segment : acc_Message_Segment );
96 entry TC_Handshake_1;
97 entry TC_Handshake_2;
98 end Sequencer;
100 task Output_Driver is
101 entry Input ( Segment : acc_Message_Segment );
102 end Output_Driver;
105 -- Simulate the arrival of three message segments in REVERSE order
107 task body TC_Simulate_Arrival is
108 begin
110 for i in 1..3 loop
111 declare
112 -- Create a task for the next message segment
113 Next_Segment_Task : acc_Carrier_Task := new Carrier_Task;
114 -- Create a record for the next segment
115 Next_Segment : acc_Message_Segment := new Message_Segment;
116 begin
117 if i = 1 then
118 -- Build the EOM segment as the first to "send"
119 Next_Segment.Seg_Sequence_No := Header + 2;
120 Next_Segment.EOM := true;
121 elsif i = 2 then
122 -- Wait for the first segment to arrive at the Sequencer
123 -- before "sending" the second
124 Sequencer.TC_Handshake_1;
125 -- Build the segment
126 Next_Segment.Seg_Sequence_No := Header + 1;
127 else
128 -- Wait for the second segment to arrive at the Sequencer
129 -- before "sending" the third
130 Sequencer.TC_Handshake_2;
131 -- Build the segment. The last segment in order to
132 -- arrive will be the "header" segment
133 Next_Segment.Seg_Sequence_No := Header;
134 end if;
135 -- pass the record to its carrier
136 Next_Segment_Task.Input ( Next_Segment );
137 end;
138 end loop;
139 exception
140 when others =>
141 Report.Failed ("Unexpected Exception in TC_Simulate_Arrival");
142 end TC_Simulate_Arrival;
145 -- One of these is generated for each message segment and the flow
146 -- of the segments through the system is controlled by the calls the
147 -- task makes and the requeues of those calls
149 task body Carrier_Task is
150 This_Segment : acc_Message_Segment := new Message_Segment;
151 begin
152 accept Input ( Segment : acc_Message_Segment ) do
153 This_Segment.all := Segment.all;
154 end Input;
155 null; --:: stub. Pass the segment around the application as needed
157 -- Now output the segment to the Output_Driver. First we have to
158 -- go through the Sequencer.
159 Sequencer.Ordering_Queue ( This_Segment );
160 exception
161 when others =>
162 Report.Failed ("Unexpected Exception in Carrier_Task");
163 end Carrier_Task;
166 -- Pull segments off the Ordering_Queue and deliver them in the correct
167 -- sequence to the Output_Driver.
169 task body Sequencer is
170 Next_Needed : Segment_Sequence := Header;
172 TC_Await_Arrival : Boolean := true;
173 TC_First_Cycle : Boolean := true;
174 TC_Expected_Sequence : Segment_Sequence := Header+2;
175 begin
176 loop
177 select
178 accept Ordering_Queue ( Segment : acc_Message_Segment ) do
180 --=====================================================
181 -- This part is all Test_Control code
183 if TC_Await_Arrival then
184 -- We have to arrange that the segments arrive on the
185 -- queue in the right order, so we handshake with the
186 -- TC_Simulate_Arrival task to "send" only one at
187 -- a time
188 accept TC_Handshake_1; -- the first has arrived
189 -- and has been pulled off the
190 -- queue
192 -- Wait for the second to arrive (the first has already
193 -- been pulled off the queue
194 while Ordering_Queue'count < 1 loop
195 delay ImpDef.Minimum_Task_Switch;
196 end loop;
198 accept TC_Handshake_2; -- the second has arrived
200 -- Wait for the third to arrive
201 while Ordering_Queue'count < 2 loop
202 delay ImpDef.Minimum_Task_Switch;
203 end loop;
205 -- Subsequent passes through the loop, bypass this code
206 TC_Await_Arrival := false;
209 end if; -- await arrival
211 if TC_First_Cycle then
212 -- Check the order of the original three
213 if Segment.Seg_Sequence_No /= TC_Expected_Sequence then
214 -- The segments are not being pulled off in the
215 -- expected sequence. This could occur if the
216 -- requeue is not putting them back on the end.
217 Report.Failed ("Sequencer: Segment out of sequence");
218 end if; -- sequence check
219 -- Decrement the expected sequence
220 if TC_Expected_Sequence /= Header then
221 TC_Expected_Sequence := TC_Expected_Sequence - 1;
222 else
223 TC_First_Cycle := false; -- This is the Header - the
224 -- first two segments are
225 -- back on the queue
227 end if; -- decrementing
228 end if; -- first pass
229 --=====================================================
231 -- And this is the Application code
232 if Segment.Seg_Sequence_No = Next_Needed then
233 if Segment.EOM then
234 Next_Needed := Header; -- reset for next message
235 else
236 Next_Needed := Next_Needed + 1;
237 end if;
238 requeue Output_Driver.Input with abort;
239 Report.Failed ("Requeue did not complete accept body");
240 else
241 -- Not the next needed - put it back on the queue
242 requeue Sequencer.Ordering_Queue;
243 Report.Failed ("Requeue did not complete accept body");
244 end if;
245 end Ordering_Queue;
247 terminate;
248 end select;
249 end loop;
250 exception
251 when others =>
252 Report.Failed ("Unexpected Exception in Sequencer");
253 end Sequencer;
256 task body Output_Driver is
257 This_Segment : acc_Message_Segment := new Message_Segment;
259 TC_Expected_Sequence : Segment_Sequence := Segment_Sequence'first;
260 TC_Segment_Total : integer := 0;
261 TC_Expected_Total : integer := 3;
262 begin
263 loop
264 -- Note: normally we would expect this Accept to be in a select
265 -- with terminate. For the test we exit the loop on completion
266 -- to give better control
267 accept Input ( Segment : acc_Message_Segment ) do
268 This_Segment.all := Segment.all;
269 end Input;
271 null; --::: stub - output the next segment of the message
273 -- The following is all test control code
275 if This_Segment.Seg_Sequence_No /= TC_Expected_Sequence then
276 Report.Failed ("Output_Driver: Segment out of sequence");
277 end if;
278 TC_Expected_Sequence := TC_Expected_Sequence + 1;
280 -- Now count the number of segments
281 TC_Segment_Total := TC_Segment_Total + 1;
283 -- Check the number and exit loop when complete
284 -- There must be exactly TC_Expected_Total in number and
285 -- the last one must be EOM
286 -- (test will hang if < TC_Expected_Total arrive
287 -- without EOM)
288 if This_Segment.EOM then
289 -- This is the last segment.
290 if TC_Segment_Total /= TC_Expected_Total then
291 Report.Failed ("EOM and wrong number of segments");
292 end if;
293 exit; -- the loop and terminate the task
294 elsif TC_Segment_Total = TC_Expected_Total then
295 Report.Failed ("No EOM found");
296 exit;
297 end if;
298 end loop;
299 exception
300 when others =>
301 Report.Failed ("Unexpected Exception in Output_Driver");
302 end Output_Driver;
306 begin
308 null;
310 end; -- encapsulation
312 Report.Result;
314 end C954019;