-- C761007.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 if a finalize procedure invoked by a transfer of control -- due to selection of a terminate alternative attempts to propagate an -- exception, the exception is ignored, but any other finalizations due -- to be performed are performed. -- -- -- TEST DESCRIPTION: -- This test declares a nested controlled data type, and embeds an object -- of that type within a protected type. Objects of the protected type -- are created and destroyed, and the actions of the embedded controlled -- object are checked. The container controlled type causes an exception -- as the last part of it's finalization operation. -- -- This test utilizes several tasks to accomplish the objective. The -- tasks contain delays to ensure that the expected order of processing -- is indeed accomplished. -- -- Subtest 1: -- local task object runs to normal completion -- -- Subtest 2: -- local task aborts a nested task to cause finalization -- -- Subtest 3: -- local task sleeps long enough to allow procedure started -- asynchronously to go into infinite loop. Procedure is then aborted -- via ATC, causing finalization of objects. -- -- Subtest 4: -- local task object takes terminate alternative, causing finalization -- -- -- CHANGE HISTORY: -- 06 JUN 95 SAIC Initial version -- 05 APR 96 SAIC Documentation changes -- 03 MAR 97 PWB.CTA Allowed two finalization orders for ATC test -- 02 DEC 97 EDS Remove duplicate characters from check string. --! ---------------------------------------------------------------- C761007_0 with Ada.Finalization; package C761007_0 is type Internal is new Ada.Finalization.Controlled with record Effect : Character; end record; procedure Finalize( I: in out Internal ); Side_Effect : String(1..80); -- way bigger than needed Side_Effect_Finger : Natural := 0; end C761007_0; -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- with TCTouch; package body C761007_0 is procedure Finalize( I : in out Internal ) is Previous_Side_Effect : Boolean := False; begin -- look to see if this character has been finalized yet for SEI in 1..Side_Effect_Finger loop Previous_Side_Effect := Previous_Side_Effect or Side_Effect(Side_Effect_Finger) = I.Effect; end loop; -- if not, then tack it on to the string, and touch the character if not Previous_Side_Effect then Side_Effect_Finger := Side_Effect_Finger +1; Side_Effect(Side_Effect_Finger) := I.Effect; TCTouch.Touch(I.Effect); end if; end Finalize; end C761007_0; ---------------------------------------------------------------- C761007_1 with C761007_0; with Ada.Finalization; package C761007_1 is type Container is new Ada.Finalization.Controlled with record Effect : Character; Content : C761007_0.Internal; end record; procedure Finalize( C: in out Container ); Side_Effect : String(1..80); -- way bigger than needed Side_Effect_Finger : Natural := 0; This_Exception_Is_Supposed_To_Be_Ignored : exception; end C761007_1; -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- with TCTouch; package body C761007_1 is procedure Finalize( C: in out Container ) is Previous_Side_Effect : Boolean := False; begin -- look to see if this character has been finalized yet for SEI in 1..Side_Effect_Finger loop Previous_Side_Effect := Previous_Side_Effect or Side_Effect(Side_Effect_Finger) = C.Effect; end loop; -- if not, then tack it on to the string, and touch the character if not Previous_Side_Effect then Side_Effect_Finger := Side_Effect_Finger +1; Side_Effect(Side_Effect_Finger) := C.Effect; TCTouch.Touch(C.Effect); end if; raise This_Exception_Is_Supposed_To_Be_Ignored; end Finalize; end C761007_1; ---------------------------------------------------------------- C761007_2 with C761007_1; package C761007_2 is protected type Prot_W_Fin_Obj is procedure Set_Effects( Container, Filling: Character ); private The_Data_Under_Test : C761007_1.Container; -- finalization for this will occur when the Prot_W_Fin_Obj object -- "goes out of existence" for whatever reason. end Prot_W_Fin_Obj; end C761007_2; -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- package body C761007_2 is protected body Prot_W_Fin_Obj is procedure Set_Effects( Container, Filling: Character ) is begin The_Data_Under_Test.Effect := Container; -- A, etc. The_Data_Under_Test.Content.Effect := Filling; -- B, etc. end Set_Effects; end Prot_W_Fin_Obj; end C761007_2; ------------------------------------------------------------------ C761007 with Report; with Impdef; with TCTouch; with C761007_0; with C761007_1; with C761007_2; procedure C761007 is task type Subtests( Outer, Inner : Character) is entry Ready; entry Complete; end Subtests; task body Subtests is Local_Prot_W_Fin_Obj : C761007_2.Prot_W_Fin_Obj; begin Local_Prot_W_Fin_Obj.Set_Effects( Outer, Inner ); accept Ready; select accept Complete; or terminate; -- used in Subtest 4 end select; exception -- the exception caused by the finalization of Local_Prot_W_Fin_Obj -- should never be visible to this scope. when others => Report.Failed("Exception in a Subtest object " & Outer & Inner); end Subtests; procedure Subtest_1 is -- check the case where "nothing special" happens. This_Subtest : Subtests( 'A', 'B' ); begin This_Subtest.Ready; This_Subtest.Complete; while not This_Subtest'Terminated loop -- wait for finalization delay Impdef.Clear_Ready_Queue; end loop; -- in the finalization of This_Subtest, the controlled object embedded in -- the Prot_W_Fin_Obj will finalize. An exception is raised in the -- container object, after "touching" it's tag character. -- The finalization of the contained controlled object must be performed. TCTouch.Validate( "AB", "Item embedded in task" ); exception when others => Report.Failed("Undesirable exception in Subtest_1"); end Subtest_1; procedure Subtest_2 is -- check for explicit abort task Subtest_Task is entry Complete; end Subtest_Task; task body Subtest_Task is task Nesting; task body Nesting is Deep_Nesting : Subtests( 'E', 'F' ); begin if Report.Ident_Bool( True ) then -- controlled objects have been created in the elaboration of -- Deep_Nesting. Deep_Nesting must call the Set_Effects operation -- in the Prot_W_Fin_Obj, and then hang waiting for the Complete -- entry call. Deep_Nesting.Ready; abort Deep_Nesting; else Report.Failed("Dead code in Nesting"); end if; exception when others => Report.Failed("Exception in Subtest_Task.Nesting"); end Nesting; Local_2 : C761007_2.Prot_W_Fin_Obj; begin -- Nesting has activated at this point, which implies the activation -- of Deep_Nesting as well. Local_2.Set_Effects( 'C', 'D' ); -- wait for Nesting to terminate while not Nesting'Terminated loop delay Impdef.Clear_Ready_Queue; end loop; accept Complete; exception when others => Report.Failed("Exception in Subtest_Task"); end Subtest_Task; begin -- wait for everything in Subtest_Task to happen Subtest_Task.Complete; while not Subtest_Task'Terminated loop -- wait for finalization delay Impdef.Clear_Ready_Queue; end loop; TCTouch.Validate( "EFCD", "Aborted nested task" ); exception when others => Report.Failed("Undesirable exception in Subtest_2"); end Subtest_2; procedure Subtest_3 is -- check abort caused by asynchronous transfer of control task Subtest_3_Task is entry Complete; end Subtest_3_Task; procedure Check_Atc_Operation is Check_Atc : C761007_2.Prot_W_Fin_Obj; begin Check_Atc.Set_Effects( 'G', 'H' ); while Report.Ident_Bool( True ) loop -- wait to be aborted if Report.Ident_Bool( True ) then Impdef.Exceed_Time_Slice; delay Impdef.Switch_To_New_Task; else Report.Failed("Optimization prevention"); end if; end loop; Report.Failed("Check_Atc_Operation loop completed"); end Check_Atc_Operation; task body Subtest_3_Task is task Nesting is entry Complete; end Nesting; task body Nesting is Nesting_3 : C761007_2.Prot_W_Fin_Obj; begin Nesting_3.Set_Effects( 'G', 'H' ); -- give Check_Atc_Operation sufficient time to perform it's -- Set_Effects on it's local Prot_W_Fin_Obj object delay Impdef.Clear_Ready_Queue; accept Complete; exception when others => Report.Failed("Exception in Subtest_3_Task.Nesting"); end Nesting; Local_3 : C761007_2.Prot_W_Fin_Obj; begin -- Subtest_3_Task Local_3.Set_Effects( 'I', 'J' ); select Nesting.Complete; then abort ---------------------------------------------------- cause KL Check_ATC_Operation; end select; accept Complete; exception when others => Report.Failed("Exception in Subtest_3_Task"); end Subtest_3_Task; begin -- Subtest_3 Subtest_3_Task.Complete; while not Subtest_3_Task'Terminated loop -- wait for finalization delay Impdef.Clear_Ready_Queue; end loop; TCTouch.Validate( "GHIJ", "Asynchronously aborted operation" ); exception when others => Report.Failed("Undesirable exception in Subtest_3"); end Subtest_3; procedure Subtest_4 is -- check the case where transfer is caused by terminate alternative -- highly similar to Subtest_1 This_Subtest : Subtests( 'M', 'N' ); begin This_Subtest.Ready; -- don't call This_Subtest.Complete; exception when others => Report.Failed("Undesirable exception in Subtest_4"); end Subtest_4; begin -- Main test procedure. Report.Test ("C761007", "Check that if a finalize procedure invoked by " & "a transfer of control or selection of a " & "terminate alternative attempts to propagate " & "an exception, the exception is ignored, but " & "any other finalizations due to be performed " & "are performed" ); Subtest_1; -- checks internal Subtest_2; -- checks internal Subtest_3; -- checks internal Subtest_4; TCTouch.Validate( "MN", "transfer due to terminate alternative" ); Report.Result; end C761007;