1-- C954015.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. 15-- 16-- DISCLAIMER 17-- 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--* 25-- 26-- OBJECTIVE: 27-- Check that requeued calls to task entries may, in turn, be requeued. 28-- Check that the intermediate requeues are not blocked and that the 29-- original caller remains blocked until the last requeue is complete. 30-- This test uses: 31-- Call with parameters 32-- Requeue with abort 33-- 34-- TEST DESCRIPTION 35-- A call is placed on the input queue of the Distributor. The 36-- Distributor requeues to the Credit task; the Credit task requeues to a 37-- secondary task which, in turn requeues to yet another task. This 38-- continues down the chain. At the furthest point of the chain the 39-- rendezvous is completed. To verify the action, the furthest task 40-- waits in the accept statement for a second message to arrive before 41-- completing. This second message can only arrive if none of the earlier 42-- tasks in the chain are blocked waiting for completion. Apart from 43-- the two Credit messages which are used to check the requeue chain one 44-- Debit message is sent to validate the mix. 45-- 46-- 47-- This series of tests uses a simulation of a transaction driven 48-- processing system. Line Drivers accept input from an external source 49-- and build them into transaction records. These records are then 50-- encapsulated in message tasks which remain extant for the life of the 51-- transaction in the system. The message tasks put themselves on the 52-- input queue of a Distributor which, from information in the 53-- transaction and/or system load conditions forwards them to other 54-- operating tasks. These in turn might forward the transactions to yet 55-- other tasks for further action. The routing is, in real life, dynamic 56-- and unpredictable at the time of message generation. All rerouting in 57-- this model is done by means of requeues. 58-- 59-- 60-- CHANGE HISTORY: 61-- 06 Dec 94 SAIC ACVC 2.0 62-- 63--! 64 65 66with Report; 67with ImpDef; 68 69procedure C954015 is 70 71 -- Arbitrary test values 72 Credit_Return : constant := 1; 73 Debit_Return : constant := 2; 74 75 -- Mechanism to count the number of Credit Message tasks completed 76 protected TC_Tasks_Completed is 77 procedure Increment; 78 function Count return integer; 79 private 80 Number_Complete : integer := 0; 81 end TC_Tasks_Completed; 82 83 TC_Expected_To_Complete : constant integer := 3; 84 85 86 -- Values added to the Return_Value indicating passage through the 87 -- particular task 88 TC_Credit_Value : constant integer := 1; 89 TC_Sub_1_Value : constant integer := 2; 90 TC_Sub_2_Value : constant integer := 3; 91 TC_Sub_3_Value : constant integer := 4; 92 TC_Sub_4_Value : constant integer := 5; 93 -- 94 TC_Full_Value : integer := TC_Credit_Value + TC_Sub_1_Value + 95 TC_Sub_2_Value + TC_Sub_3_Value + 96 TC_Sub_4_Value; 97 98 type Transaction_Code is (Credit, Debit); 99 100 type Transaction_Record; 101 type acc_Transaction_Record is access Transaction_Record; 102 type Transaction_Record is 103 record 104 ID : integer := 0; 105 Code : Transaction_Code := Debit; 106 Account_Number : integer := 0; 107 Stock_Number : integer := 0; 108 Quantity : integer := 0; 109 Return_Value : integer := 0; 110 TC_Message_Count : integer := 0; 111 TC_Thru_Distrib : Boolean := false; 112 end record; 113 114 115 task type Message_Task is 116 entry Accept_Transaction (In_Transaction : acc_Transaction_Record); 117 end Message_Task; 118 type acc_Message_Task is access Message_Task; 119 120 task Line_Driver is 121 entry Start; 122 end Line_Driver; 123 124 task Distributor is 125 entry Input(Transaction : acc_Transaction_Record); 126 end Distributor; 127 128 task Credit_Computation is 129 entry Input(Transaction : acc_Transaction_Record); 130 end Credit_Computation; 131 132 task Debit_Computation is 133 entry Input(Transaction : acc_Transaction_Record); 134 end Debit_Computation; 135 136 -- The following are almost identical for the purpose of the test 137 task Credit_Sub_1 is 138 entry Input(Transaction : acc_Transaction_Record); 139 end Credit_Sub_1; 140 -- 141 task Credit_Sub_2 is 142 entry Input(Transaction : acc_Transaction_Record); 143 end Credit_Sub_2; 144 -- 145 task Credit_Sub_3 is 146 entry Input(Transaction : acc_Transaction_Record); 147 end Credit_Sub_3; 148 149 -- This is the last in the chain 150 task Credit_Sub_4 is 151 entry Input(Transaction : acc_Transaction_Record); 152 end Credit_Sub_4; 153 154 155 -- Mechanism to count the number of Message tasks completed (Credit) 156 protected body TC_Tasks_Completed is 157 procedure Increment is 158 begin 159 Number_Complete := Number_Complete + 1; 160 end Increment; 161 162 function Count return integer is 163 begin 164 return Number_Complete; 165 end Count; 166 end TC_Tasks_Completed; 167 168 169 170 -- Assemble messages received from an external source 171 -- Creates a message task for each. The message tasks remain extant 172 -- for the life of the messages in the system. 173 -- The Line Driver task would normally be designed to loop continuously 174 -- creating the messages as input is received. Simulate this 175 -- but limit it to the number of dummy messages needed for this 176 -- test and allow it to terminate at that point. 177 -- 178 task body Line_Driver is 179 Current_ID : integer := 1; 180 TC_Last_was_for_credit : Boolean := false; 181 182 -- Arbitrary limit for the number of messages sent for this test 183 type TC_Trans_Range is range 1..3; 184 185 procedure Build_Credit_Record 186 ( Next_Transaction : acc_Transaction_Record ) is 187 Dummy_Account : constant integer := 100; 188 begin 189 Next_Transaction.ID := Current_ID; 190 Next_Transaction.Code := Credit; 191 Next_Transaction.Account_Number := Dummy_Account; 192 Current_ID := Current_ID + 1; 193 end Build_Credit_Record; 194 195 procedure Build_Debit_Record 196 ( Next_Transaction : acc_Transaction_Record ) is 197 Dummy_Account : constant integer := 200; 198 begin 199 Next_Transaction.ID := Current_ID; 200 Next_Transaction.Code := Debit; 201 Next_Transaction.Account_Number := Dummy_Account; 202 Current_ID := Current_ID + 1; 203 end Build_Debit_Record; 204 205 206 begin 207 208 accept Start; -- wait for trigger from Main 209 210 -- Arbitrarily limit the loop to the number needed for this test only 211 for Transaction_Numb in TC_Trans_Range loop 212 declare 213 -- Create a task for the next message 214 Next_Message_Task : acc_Message_Task := new Message_Task; 215 -- Create a record for it 216 Next_Transaction : acc_Transaction_Record := 217 new Transaction_Record; 218 begin 219 -- Artificially send out in the order required 220 case Transaction_Numb is 221 when 1 => 222 Build_Credit_Record( Next_Transaction ); 223 when 2 => 224 Build_Credit_Record( Next_Transaction ); 225 when 3 => 226 Build_Debit_Record ( Next_Transaction ); 227 end case; 228 229 -- Present the record to the message task 230 Next_Message_Task.Accept_Transaction ( Next_Transaction ); 231 end; -- declare 232 end loop; 233 234 exception 235 when others => 236 Report.Failed ("Unexpected exception in Line_Driver"); 237 end Line_Driver; 238 239 240 241 task body Message_Task is 242 243 TC_Original_Transaction_Code : Transaction_Code; 244 This_Transaction : acc_Transaction_Record := new Transaction_Record; 245 246 begin 247 248 accept Accept_Transaction (In_Transaction : acc_Transaction_Record) do 249 This_Transaction.all := In_Transaction.all; 250 end Accept_Transaction; 251 252 -- Note the original code to ensure correct return 253 TC_Original_Transaction_Code := This_Transaction.Code; 254 255 -- Queue up on Distributor's Input queue 256 Distributor.Input ( This_Transaction ); 257 -- This task will now wait for the requeued rendezvous 258 -- to complete before proceeding 259 260 -- After the required computations have been performed 261 -- return the Transaction_Record appropriately (probably to an output 262 -- line driver) 263 null; -- stub 264 265 266 -- The following is all Test Control Code 267 268 -- Check that the return values are as expected 269 if TC_Original_Transaction_Code /= This_Transaction.Code then 270 -- Incorrect rendezvous 271 Report.Failed ("Message Task: Incorrect code returned"); 272 end if; 273 274 if This_Transaction.Code = Credit then 275 if This_Transaction.Return_Value /= TC_Full_Value or not 276 This_Transaction.TC_Thru_Distrib then 277 Report.Failed ("Expected path not traversed - CR"); 278 end if; 279 if 280 This_Transaction.TC_Message_Count not in 1..2 then 281 Report.Failed ("Incorrect Message Count"); 282 end if; 283 else 284 if This_Transaction.Return_Value /= Debit_Return or 285 This_Transaction.TC_Message_Count /= 1 or not 286 This_Transaction.TC_Thru_Distrib then 287 Report.Failed ("Expected path not traversed - DB"); 288 end if; 289 end if; 290 TC_Tasks_Completed.Increment; 291 exception 292 when others => 293 Report.Failed ("Unexpected exception in Message_Task"); 294 295 end Message_Task; 296 297 298 299 -- Dispose each input Transaction_Record to the appropriate 300 -- computation tasks 301 -- 302 task body Distributor is 303 304 begin 305 loop 306 select 307 accept Input (Transaction : acc_Transaction_Record) do 308 -- Show that the message did pass through the Distributor Task 309 Transaction.TC_Thru_Distrib := true; 310 311 -- Pass this transaction on to the appropriate computation 312 -- task 313 case Transaction.Code is 314 when Credit => 315 requeue Credit_Computation.Input with abort; 316 when Debit => 317 requeue Debit_Computation.Input with abort; 318 end case; 319 end Input; 320 or 321 terminate; 322 end select; 323 end loop; 324 325 exception 326 when others => 327 Report.Failed ("Unexpected exception in Distributor"); 328 end Distributor; 329 330 331 332 333 -- Computation task. 334 -- Note: After the computation is performed in this task the message is 335 -- passed on for further processing to some subsidiary task. The choice 336 -- of subsidiary task is made according to criteria not specified in 337 -- this test. 338 -- 339 task body Credit_Computation is 340 Message_Count : integer := 0; 341 begin 342 loop 343 select 344 accept Input ( Transaction : acc_Transaction_Record) do 345 -- Perform the computations required for this transaction 346 null; -- stub 347 348 -- For the test: 349 if not Transaction.TC_Thru_Distrib then 350 Report.Failed 351 ("Credit Task: Wrong queue, Distributor bypassed"); 352 end if; 353 if Transaction.code /= Credit then 354 Report.Failed 355 ("Credit Task: Requeue delivered to the wrong queue"); 356 end if; 357 358 -- for the test, plug a known value and count 359 Transaction.Return_Value := TC_Credit_Value; 360 Message_Count := Message_Count + 1; 361 Transaction.TC_Message_Count := Message_Count; 362 363 -- Depending on transaction content send it on to the 364 -- some other task for further processing 365 -- TC: Arbitrarily send the message on to Credit_Sub_1 366 requeue Credit_Sub_1.Input with abort; 367 end Input; 368 or 369 terminate; 370 end select; 371 end loop; 372 exception 373 when others => 374 Report.Failed ("Unexpected exception in Credit_Computation"); 375 end Credit_Computation; 376 377 378 379 task body Credit_Sub_1 is 380 begin 381 loop 382 select 383 accept Input(Transaction : acc_Transaction_Record) do 384 -- Process this transaction 385 null; -- stub 386 387 -- Add the value showing passage through this task 388 Transaction.Return_Value := 389 Transaction.Return_Value + TC_Sub_1_Value; 390 -- Depending on transaction content send it on to the 391 -- some other task for further processing 392 -- Arbitrarily send the message on to Credit_Sub_2 393 requeue Credit_Sub_2.Input with abort; 394 end Input; 395 or 396 terminate; 397 end select; 398 end loop; 399 exception 400 when others => 401 Report.Failed ("Unexpected exception in Credit_Sub_1"); 402 403 end Credit_Sub_1; 404 405 task body Credit_Sub_2 is 406 begin 407 loop 408 select 409 accept Input(Transaction : acc_Transaction_Record) do 410 -- Process this transaction 411 null; -- stub 412 413 -- Add the value showing passage through this task 414 Transaction.Return_Value := 415 Transaction.Return_Value + TC_Sub_2_Value; 416 -- Depending on transaction content send it on to the 417 -- some other task for further processing 418 -- Arbitrarily send the message on to Credit_Sub_3 419 requeue Credit_Sub_3.Input with abort; 420 end Input; 421 or 422 terminate; 423 end select; 424 end loop; 425 exception 426 when others => 427 Report.Failed ("Unexpected exception in Credit_Sub_2"); 428 end Credit_Sub_2; 429 430 task body Credit_Sub_3 is 431 begin 432 loop 433 select 434 accept Input(Transaction : acc_Transaction_Record) do 435 -- Process this transaction 436 null; -- stub 437 438 -- Add the value showing passage through this task 439 Transaction.Return_Value := 440 Transaction.Return_Value + TC_Sub_3_Value; 441 -- Depending on transaction content send it on to the 442 -- some other task for further processing 443 -- Arbitrarily send the message on to Credit_Sub_4 444 requeue Credit_Sub_4.Input with abort; 445 end Input; 446 or 447 terminate; 448 end select; 449 end loop; 450 exception 451 when others => 452 Report.Failed ("Unexpected exception in Credit_Sub_3"); 453 end Credit_Sub_3; 454 455 -- This is the last in the chain of tasks to which transactions will 456 -- be requeued 457 -- 458 task body Credit_Sub_4 is 459 460 TC_First_Message : Boolean := true; 461 462 begin 463 loop 464 select 465 accept Input(Transaction : acc_Transaction_Record) do 466 -- Process this transaction 467 null; -- stub 468 469 -- Add the value showing passage through this task 470 Transaction.Return_Value := 471 Transaction.Return_Value + TC_Sub_4_Value; 472 -- TC: stay in the accept body dealing with the first message 473 -- until the second arrives. If any of the requeues are 474 -- blocked the test will hang here indicating failure 475 if TC_First_Message then 476 while Input'count = 0 loop 477 delay ImpDef.Minimum_Task_Switch; 478 end loop; 479 TC_First_Message := false; 480 end if; 481 -- for the second message, just complete the rendezvous 482 end Input; 483 or 484 terminate; 485 end select; 486 end loop; 487 exception 488 when others => 489 Report.Failed ("Unexpected exception in Credit_Sub_4"); 490 end Credit_Sub_4; 491 492 493 494 -- Computation task. 495 -- Note: After the computation is performed in this task and the 496 -- accept body is completed the rendezvous in the original 497 -- message task is completed. 498 -- 499 task body Debit_Computation is 500 Message_Count : integer := 0; 501 begin 502 loop 503 select 504 accept Input (Transaction : acc_Transaction_Record) do 505 -- Perform the computations required for this message 506 null; -- stub 507 508 -- For the test: 509 if not Transaction.TC_Thru_Distrib then 510 Report.Failed 511 ("Debit Task: Wrong queue, Distributor bypassed"); 512 end if; 513 if Transaction.code /= Debit then 514 Report.Failed 515 ("Debit Task: Requeue delivered to the wrong queue"); 516 end if; 517 518 -- for the test plug a known value and count 519 Transaction.Return_Value := Debit_Return; 520 -- one, and only one, message should pass through 521 Message_Count := Message_Count + 1; 522 Transaction.TC_Message_Count := Message_Count; 523 end Input; 524 or 525 terminate; 526 end select; 527 end loop; 528 exception 529 when others => 530 Report.Failed ("Unexpected exception in Debit_Computation"); 531 532 533 end Debit_Computation; 534 535 536begin 537 538 Report.Test ("C954015", "Test multiple levels of requeue to task entry"); 539 540 Line_Driver.Start; -- Start the test 541 542 -- Ensure that the message tasks completed before calling Result 543 while (TC_Tasks_Completed.Count < TC_Expected_To_Complete) loop 544 delay ImpDef.Minimum_Task_Switch; 545 end loop; 546 547 Report.Result; 548 549end C954015; 550