> Downside is that those 5 ClassTestCase tests will be executed too often.<br>
<br>
Could this be a case for overriding #shouldInheritSelectors?<br>
<br>
Best,<br>
Christoph<br>
<br>
<font color="#808080">---<br>
</font><font color="#808080"><i>Sent from </i></font><font color="#808080"><i><a href="https://github.com/hpi-swa-lab/squeak-inbox-talk"><u><font color="#808080">Squeak Inbox Talk</font></u></a></i></font><br>
<br>
On 2022-05-31T13:24:36+00:00, commits@source.squeak.org wrote:<br>
<br>
> Marcel Taeumel uploaded a new version of KernelTests to project The Trunk:<br>
> http://source.squeak.org/trunk/KernelTests-mt.424.mcz<br>
> <br>
> ==================== Summary ====================<br>
> <br>
> Name: KernelTests-mt.424<br>
> Author: mt<br>
> Time: 31 May 2022, 3:24:36.006029 pm<br>
> UUID: 54f976c3-1296-964f-9a2a-1890202ae545<br>
> Ancestors: KernelTests-jar.423<br>
> <br>
> Moves ProcessTerminateBug from Tests to KernelTests package.<br>
> <br>
> Makes re-used semaphore in (Process)UnwindTest more explicit by having an AbstractProcessTest. Downside is that those 5 ClassTestCase tests will be executed too often.<br>
> <br>
> Thanks to Jaromir (jar) for the pointer!<br>
> <br>
> =============== Diff against KernelTests-jar.423 ===============<br>
> <br>
> Item was added:<br>
> + ClassTestCase subclass: #AbstractProcessTest<br>
> +     instanceVariableNames: 'semaphore'<br>
> +     classVariableNames: ''<br>
> +     poolDictionaries: ''<br>
> +     category: 'KernelTests-Processes'!<br>
> <br>
> Item was added:<br>
> + ----- Method: AbstractProcessTest class>>isAbstract (in category 'testing') -----<br>
> + isAbstract<br>
> + <br>
> +     ^ self name = #AbstractProcessTest!<br>
> <br>
> Item was added:<br>
> + ----- Method: AbstractProcessTest>>genuineProcess (in category 'support') -----<br>
> + genuineProcess<br>
> +     "Usually, we don't want to expose this from the class under test but we need it in the test context."<br>
> + <br>
> +     ^ Processor instVarNamed: 'genuineProcess'!<br>
> <br>
> Item was added:<br>
> + ----- Method: AbstractProcessTest>>setUp (in category 'running') -----<br>
> + setUp<br>
> + <br>
> +     super setUp.<br>
> +     semaphore := Semaphore new.!<br>
> <br>
> Item was added:<br>
> + ----- Method: AbstractProcessTest>>targetClass (in category 'support') -----<br>
> + targetClass<br>
> + <br>
> +     ^ self environment classNamed: #Process!<br>
> <br>
> Item was added:<br>
> + ----- Method: AbstractProcessTest>>tearDown (in category 'running') -----<br>
> + tearDown    <br>
> +     "Release all processes still waiting at the semaphore or in the active priority queue."<br>
> + <br>
> +     Processor yield.<br>
> +     [semaphore isEmpty] whileFalse: [semaphore signal].<br>
> + <br>
> +     super tearDown.!<br>
> <br>
> Item was added:<br>
> + AbstractProcessTest subclass: #ProcessTerminateBug<br>
> +     instanceVariableNames: ''<br>
> +     classVariableNames: ''<br>
> +     poolDictionaries: ''<br>
> +     category: 'KernelTests-Processes'!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessTerminateBug>>testSchedulerTermination (in category 'tests') -----<br>
> + testSchedulerTermination<br>
> +    | process sema gotHere sema2 |<br>
> +    gotHere := false.<br>
> +    sema := Semaphore new.<br>
> +    sema2 := Semaphore new.<br>
> +    process := [<br>
> +        sema signal.<br>
> +        sema2 wait.<br>
> +        "will be suspended here"<br>
> +        gotHere := true. "e.g., we must *never* get here"<br>
> +    ] forkAt: Processor activeProcess priority.<br>
> +    sema wait. "until process gets scheduled"<br>
> +    process terminate.<br>
> +    sema2 signal.<br>
> +    Processor yield. "will give process a chance to continue and<br>
> + horribly screw up"<br>
> +    self assert: gotHere not.<br>
> + !<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessTerminateBug>>testTerminationDuringUnwind (in category 'tests') -----<br>
> + testTerminationDuringUnwind<br>
> +     "An illustration of the issue of process termination during unwind.<br>
> +     This uses a well-behaved unwind block that we should allow to complete<br>
> +     if at all possible."<br>
> +     | unwindStarted unwindFinished p |<br>
> +     unwindStarted := unwindFinished := false.<br>
> +     p := [[] ensure:[<br>
> +             unwindStarted := true.<br>
> +             Processor yield.<br>
> +             unwindFinished := true.<br>
> +         ]] fork.<br>
> +     self deny: unwindStarted.<br>
> +     Processor yield.<br>
> +     self assert: unwindStarted.<br>
> +     self deny: unwindFinished.<br>
> +     p terminate.<br>
> +     self assert: unwindFinished.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessTerminateBug>>testUnwindFromActiveProcess (in category 'tests') -----<br>
> + testUnwindFromActiveProcess<br>
> +     | sema process |<br>
> +     sema := Semaphore forMutualExclusion.<br>
> +     self assert:(sema isSignaled).<br>
> +     process := [<br>
> +         sema critical:[<br>
> +             self deny: sema isSignaled.<br>
> +             Processor activeProcess terminate.<br>
> +         ]<br>
> +     ] forkAt: Processor userInterruptPriority.<br>
> +     self assert: sema isSignaled.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessTerminateBug>>testUnwindFromForeignProcess (in category 'tests') -----<br>
> + testUnwindFromForeignProcess<br>
> +     | sema process |<br>
> +     sema := Semaphore forMutualExclusion.<br>
> +     self assert: sema isSignaled.<br>
> +     process := [<br>
> +         sema critical:[<br>
> +             self deny: sema isSignaled.<br>
> +             sema wait. "deadlock"<br>
> +         ]<br>
> +     ] forkAt: Processor userInterruptPriority.<br>
> +     self deny: sema isSignaled.<br>
> +     "This is for illustration only - the BlockCannotReturn cannot <br>
> +     be handled here (it's truncated already)"<br>
> +     self shouldnt: [process terminate] raise: BlockCannotReturn.<br>
> +     self assert: sema isSignaled.<br>
> +     !<br>
> <br>
> Item was changed:<br>
> + AbstractProcessTest subclass: #ProcessTest<br>
> +     instanceVariableNames: ''<br>
> - ClassTestCase subclass: #ProcessTest<br>
> -     instanceVariableNames: 'semaphore'<br>
>       classVariableNames: ''<br>
>       poolDictionaries: ''<br>
>       category: 'KernelTests-Processes'!<br>
>   <br>
>   !ProcessTest commentStamp: 'ul 8/16/2011 11:35' prior: 0!<br>
>   I hold test cases for generic Process-related behaviour.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: ProcessTest>>genuineProcess (in category 'support') -----<br>
> - genuineProcess<br>
> - <br>
> -     "Usually, we don't want to expose this from the class under test."<br>
> -     ^ Processor instVarNamed: 'genuineProcess'!<br>
> <br>
> Item was removed:<br>
> - ----- Method: ProcessTest>>setUp (in category 'running') -----<br>
> - setUp<br>
> -     semaphore := Semaphore new!<br>
> <br>
> Item was removed:<br>
> - ----- Method: ProcessTest>>tearDown (in category 'running') -----<br>
> - tearDown<br>
> -     Processor activeProcess environmentRemoveKey: #processTests ifAbsent: [].<br>
> -     <br>
> -     "Release all processes still waiting at the semaphore or in the active priority queue."<br>
> -     Processor yield.<br>
> -     [semaphore isEmpty] whileFalse: [semaphore signal]!<br>
> <br>
> Item was changed:<br>
> + ----- Method: ProcessTest>>testProcessFaithfulTermination: (in category 'support') -----<br>
> - ----- Method: ProcessTest>>testProcessFaithfulTermination: (in category 'tests') -----<br>
>   testProcessFaithfulTermination: terminator<br>
>       "When terminating a process, unwind blocks should be evaluated as if they were executed by the process being terminated."<br>
>   <br>
>       | process result |<br>
>       process := [<br>
>           [Processor activeProcess suspend]<br>
>               ensure: [result := Processor activeProcess environmentAt: #foo]]<br>
>           fork.<br>
>       Processor yield.<br>
>       process environmentAt: #foo put: 42.<br>
>       <br>
>       terminator value: process.<br>
>       <br>
>       self should: process isTerminated.<br>
>       self assert: 42 equals: result.!<br>
> <br>
> Item was changed:<br>
> + ----- Method: ProcessTest>>testProcessStateTestTermination: (in category 'support') -----<br>
> - ----- Method: ProcessTest>>testProcessStateTestTermination: (in category 'tests') -----<br>
>   testProcessStateTestTermination: terminator<br>
>       "I test that a process is terminated when it reaches the last instruction <br>
>       of the bottom context for methods other than Process>>#terminate; <br>
>       this test would fail with the version of isTerminated before 3/11/2021."<br>
>   <br>
>       | bottomContext newProcess |<br>
>       <br>
>       newProcess := Process new.<br>
>       bottomContext := Context <br>
>           sender: nil <br>
>           receiver: newProcess <br>
>           method: (ProcessTest>>#terminated) <br>
>           arguments: {}.<br>
>       newProcess suspendedContext: ([] asContextWithSender: bottomContext).<br>
>       newProcess priority: Processor activePriority.<br>
>       <br>
>       self deny: newProcess isTerminated.<br>
>       terminator value: newProcess.<br>
>       self assert: newProcess isTerminated.<br>
>   !<br>
> <br>
> Item was added:<br>
> + AbstractProcessTest subclass: #ProcessUnwindTest<br>
> +     instanceVariableNames: ''<br>
> +     classVariableNames: ''<br>
> +     poolDictionaries: ''<br>
> +     category: 'KernelTests-Processes'!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateActiveInNestedEnsure1 (in category 'tests') -----<br>
> + testTerminateActiveInNestedEnsure1<br>
> +     "Terminate active process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +         [<br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [Processor activeProcess terminate] ensure: [<br>
> +                         x1 := true]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true.<br>
> +         ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateActiveInNestedEnsure2 (in category 'tests') -----<br>
> + testTerminateActiveInNestedEnsure2<br>
> +     "Terminate active process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +         [<br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [ ] ensure: [<br>
> +                         Processor activeProcess terminate.<br>
> +                         x1 := true]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true.<br>
> +         ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateBlockedInNestedEnsure1 (in category 'tests') -----<br>
> + testTerminateBlockedInNestedEnsure1<br>
> +     "Terminate blocked process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +         [<br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [semaphore wait] ensure: [<br>
> +                         x1 := true]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true.<br>
> +         ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is blocked and none of the unwind blocks has finished yet"<br>
> +     self assert: p isBlocked.<br>
> +     self deny: x1 | x2 | x3 | x4.<br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateBlockedInNestedEnsure2 (in category 'tests') -----<br>
> + testTerminateBlockedInNestedEnsure2<br>
> +     "Terminate blocked process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +         [<br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [ ] ensure: [<br>
> +                         semaphore wait.<br>
> +                         x1 := true]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true.<br>
> +         ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is blocked and none of the unwind blocks has finished yet"<br>
> +     self assert: p isBlocked.<br>
> +     self deny: x1 | x2 | x3 | x4. <br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateInNestedEnsureWithReturn1 (in category 'tests') -----<br>
> + testTerminateInNestedEnsureWithReturn1<br>
> +     "Terminate suspended process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +     [<br>
> +         [:return | <br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [Processor activeProcess suspend] ensure: [<br>
> +                         x1 := true. return value]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true.<br>
> +         ] valueWithExit<br>
> +     ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> +     self assert: p isSuspended.<br>
> +     self deny: x1 | x2 | x3 | x4.<br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x3.<br>
> +     self deny: x2 & x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateInNestedEnsureWithReturn2 (in category 'tests') -----<br>
> + testTerminateInNestedEnsureWithReturn2<br>
> +     "Terminate suspended process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +     [<br>
> +         [:return | <br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [] ensure: [<br>
> +                         Processor activeProcess suspend.<br>
> +                         x1 := true. return value]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true.<br>
> +         ] valueWithExit<br>
> +     ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> +     self assert: p isSuspended.<br>
> +     self deny: x1 | x2 | x3 | x4.<br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x3.<br>
> +     self deny: x2 & x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateInNestedEnsureWithReturn3 (in category 'tests') -----<br>
> + testTerminateInNestedEnsureWithReturn3<br>
> +     "Terminate suspended process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +     [<br>
> +         [:return | <br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [Processor activeProcess suspend] ensure: [<br>
> +                         x1 := true]. <br>
> +                     x2 := true. return value]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true.<br>
> +         ] valueWithExit<br>
> +     ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> +     self assert: p isSuspended.<br>
> +     self deny: x1 | x2 | x3 | x4.<br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateInNestedEnsureWithReturn4 (in category 'tests') -----<br>
> + testTerminateInNestedEnsureWithReturn4<br>
> +     "Terminate suspended process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +     [<br>
> +         [:return | <br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [] ensure: [<br>
> +                         Processor activeProcess suspend.<br>
> +                         x1 := true]. <br>
> +                     x2 := true. return value]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true.<br>
> +         ] valueWithExit<br>
> +     ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> +     self assert: p isSuspended.<br>
> +     self deny: x1 | x2 | x3 | x4.<br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateInNestedEnsureWithReturn5 (in category 'tests') -----<br>
> + testTerminateInNestedEnsureWithReturn5<br>
> +     "Terminate suspended process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +     [<br>
> +         [:return | <br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [Processor activeProcess suspend] ensure: [<br>
> +                         x1 := true]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true. return value].<br>
> +             x4 := true.<br>
> +         ] valueWithExit<br>
> +     ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> +     self assert: p isSuspended.<br>
> +     self deny: x1 | x2 | x3 | x4.<br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateInNestedEnsureWithReturn6 (in category 'tests') -----<br>
> + testTerminateInNestedEnsureWithReturn6<br>
> +     "Terminate suspended process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +     [<br>
> +         [:return | <br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [] ensure: [<br>
> +                         Processor activeProcess suspend.<br>
> +                         x1 := true]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true. return value].<br>
> +             x4 := true.<br>
> +         ] valueWithExit<br>
> +     ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> +     self assert: p isSuspended.<br>
> +     self deny: x1 | x2 | x3 | x4.<br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateInNestedEnsureWithReturn7 (in category 'tests') -----<br>
> + testTerminateInNestedEnsureWithReturn7<br>
> +     "Terminate suspended process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +     [<br>
> +         [:return | <br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [Processor activeProcess suspend] ensure: [<br>
> +                         x1 := true]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true. return value.<br>
> +         ] valueWithExit<br>
> +     ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> +     self assert: p isSuspended.<br>
> +     self deny: x1 | x2 | x3 | x4.<br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateInNestedEnsureWithReturn8 (in category 'tests') -----<br>
> + testTerminateInNestedEnsureWithReturn8<br>
> +     "Terminate suspended process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +     [<br>
> +         [:return | <br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [] ensure: [<br>
> +                         Processor activeProcess suspend.<br>
> +                         x1 := true]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true. return value.<br>
> +         ] valueWithExit<br>
> +     ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> +     self assert: p isSuspended.<br>
> +     self deny: x1 | x2 | x3 | x4.<br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateRunnableInNestedEnsure1 (in category 'tests') -----<br>
> + testTerminateRunnableInNestedEnsure1<br>
> +     "Terminate runnable process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +         [<br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [Processor yield] ensure: [<br>
> +                         x1 := true]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true.<br>
> +         ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is runnable and none of the unwind blocks has finished yet"<br>
> +     self assert: p isRunnable.<br>
> +     self deny: x1 | x2 | x3 | x4.<br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateRunnableInNestedEnsure2 (in category 'tests') -----<br>
> + testTerminateRunnableInNestedEnsure2<br>
> +     "Terminate runnable process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +         [<br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [ ] ensure: [<br>
> +                         Processor yield. <br>
> +                         x1 := true]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true.<br>
> +         ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is runnable and none of the unwind blocks has finished yet"<br>
> +     self assert: p isRunnable.<br>
> +     self deny: x1 | x2 | x3 | x4.<br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateSuspendedInNestedEnsure1 (in category 'tests') -----<br>
> + testTerminateSuspendedInNestedEnsure1<br>
> +     "Terminate suspended process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +         [<br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [Processor activeProcess suspend] ensure: [<br>
> +                         x1 := true]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true.<br>
> +         ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> +     self assert: p isSuspended.<br>
> +     self deny: x1 | x2 | x3 | x4.<br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was added:<br>
> + ----- Method: ProcessUnwindTest>>testTerminateSuspendedInNestedEnsure2 (in category 'tests') -----<br>
> + testTerminateSuspendedInNestedEnsure2<br>
> +     "Terminate suspended process.<br>
> +     Test all nested unwind blocks are correctly executed; <br>
> +     all unwind blocks halfway through their execution should be completed."<br>
> + <br>
> +     | p x1 x2 x3 x4 |<br>
> +     x1 := x2 := x3 := x4 := false.<br>
> +     p := <br>
> +         [<br>
> +             [<br>
> +                 [ ] ensure: [<br>
> +                     [ ] ensure: [<br>
> +                         Processor activeProcess suspend. <br>
> +                         x1 := true]. <br>
> +                     x2 := true]<br>
> +             ] ensure: [<br>
> +                 x3 := true].<br>
> +             x4 := true.<br>
> +         ] newProcess.<br>
> +     p resume.<br>
> +     Processor yield.<br>
> +     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> +     self assert: p isSuspended.<br>
> +     self deny: x1 | x2 | x3 | x4.<br>
> +     "now terminate the process and make sure all unwind blocks have finished"<br>
> +     p terminate.<br>
> +     self assert: p isTerminated.<br>
> +     self assert: x1 & x2 & x3.<br>
> +     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ProcessTest subclass: #UnwindTest<br>
> -     instanceVariableNames: ''<br>
> -     classVariableNames: ''<br>
> -     poolDictionaries: ''<br>
> -     category: 'KernelTests-Processes'!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateActiveInNestedEnsure1 (in category 'tests') -----<br>
> - testTerminateActiveInNestedEnsure1<br>
> -     "Terminate active process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -         [<br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [Processor activeProcess terminate] ensure: [<br>
> -                         x1 := true]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true.<br>
> -         ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateActiveInNestedEnsure2 (in category 'tests') -----<br>
> - testTerminateActiveInNestedEnsure2<br>
> -     "Terminate active process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -         [<br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [ ] ensure: [<br>
> -                         Processor activeProcess terminate.<br>
> -                         x1 := true]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true.<br>
> -         ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateBlockedInNestedEnsure1 (in category 'tests') -----<br>
> - testTerminateBlockedInNestedEnsure1<br>
> -     "Terminate blocked process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -         [<br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [semaphore wait] ensure: [<br>
> -                         x1 := true]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true.<br>
> -         ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is blocked and none of the unwind blocks has finished yet"<br>
> -     self assert: p isBlocked.<br>
> -     self deny: x1 | x2 | x3 | x4.<br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateBlockedInNestedEnsure2 (in category 'tests') -----<br>
> - testTerminateBlockedInNestedEnsure2<br>
> -     "Terminate blocked process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -         [<br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [ ] ensure: [<br>
> -                         semaphore wait.<br>
> -                         x1 := true]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true.<br>
> -         ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is blocked and none of the unwind blocks has finished yet"<br>
> -     self assert: p isBlocked.<br>
> -     self deny: x1 | x2 | x3 | x4. <br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateInNestedEnsureWithReturn1 (in category 'tests') -----<br>
> - testTerminateInNestedEnsureWithReturn1<br>
> -     "Terminate suspended process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -     [<br>
> -         [:return | <br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [Processor activeProcess suspend] ensure: [<br>
> -                         x1 := true. return value]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true.<br>
> -         ] valueWithExit<br>
> -     ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> -     self assert: p isSuspended.<br>
> -     self deny: x1 | x2 | x3 | x4.<br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x3.<br>
> -     self deny: x2 & x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateInNestedEnsureWithReturn2 (in category 'tests') -----<br>
> - testTerminateInNestedEnsureWithReturn2<br>
> -     "Terminate suspended process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -     [<br>
> -         [:return | <br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [] ensure: [<br>
> -                         Processor activeProcess suspend.<br>
> -                         x1 := true. return value]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true.<br>
> -         ] valueWithExit<br>
> -     ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> -     self assert: p isSuspended.<br>
> -     self deny: x1 | x2 | x3 | x4.<br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x3.<br>
> -     self deny: x2 & x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateInNestedEnsureWithReturn3 (in category 'tests') -----<br>
> - testTerminateInNestedEnsureWithReturn3<br>
> -     "Terminate suspended process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -     [<br>
> -         [:return | <br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [Processor activeProcess suspend] ensure: [<br>
> -                         x1 := true]. <br>
> -                     x2 := true. return value]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true.<br>
> -         ] valueWithExit<br>
> -     ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> -     self assert: p isSuspended.<br>
> -     self deny: x1 | x2 | x3 | x4.<br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateInNestedEnsureWithReturn4 (in category 'tests') -----<br>
> - testTerminateInNestedEnsureWithReturn4<br>
> -     "Terminate suspended process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -     [<br>
> -         [:return | <br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [] ensure: [<br>
> -                         Processor activeProcess suspend.<br>
> -                         x1 := true]. <br>
> -                     x2 := true. return value]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true.<br>
> -         ] valueWithExit<br>
> -     ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> -     self assert: p isSuspended.<br>
> -     self deny: x1 | x2 | x3 | x4.<br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateInNestedEnsureWithReturn5 (in category 'tests') -----<br>
> - testTerminateInNestedEnsureWithReturn5<br>
> -     "Terminate suspended process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -     [<br>
> -         [:return | <br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [Processor activeProcess suspend] ensure: [<br>
> -                         x1 := true]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true. return value].<br>
> -             x4 := true.<br>
> -         ] valueWithExit<br>
> -     ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> -     self assert: p isSuspended.<br>
> -     self deny: x1 | x2 | x3 | x4.<br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateInNestedEnsureWithReturn6 (in category 'tests') -----<br>
> - testTerminateInNestedEnsureWithReturn6<br>
> -     "Terminate suspended process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -     [<br>
> -         [:return | <br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [] ensure: [<br>
> -                         Processor activeProcess suspend.<br>
> -                         x1 := true]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true. return value].<br>
> -             x4 := true.<br>
> -         ] valueWithExit<br>
> -     ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> -     self assert: p isSuspended.<br>
> -     self deny: x1 | x2 | x3 | x4.<br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateInNestedEnsureWithReturn7 (in category 'tests') -----<br>
> - testTerminateInNestedEnsureWithReturn7<br>
> -     "Terminate suspended process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -     [<br>
> -         [:return | <br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [Processor activeProcess suspend] ensure: [<br>
> -                         x1 := true]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true. return value.<br>
> -         ] valueWithExit<br>
> -     ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> -     self assert: p isSuspended.<br>
> -     self deny: x1 | x2 | x3 | x4.<br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateInNestedEnsureWithReturn8 (in category 'tests') -----<br>
> - testTerminateInNestedEnsureWithReturn8<br>
> -     "Terminate suspended process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -     [<br>
> -         [:return | <br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [] ensure: [<br>
> -                         Processor activeProcess suspend.<br>
> -                         x1 := true]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true. return value.<br>
> -         ] valueWithExit<br>
> -     ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> -     self assert: p isSuspended.<br>
> -     self deny: x1 | x2 | x3 | x4.<br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateRunnableInNestedEnsure1 (in category 'tests') -----<br>
> - testTerminateRunnableInNestedEnsure1<br>
> -     "Terminate runnable process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -         [<br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [Processor yield] ensure: [<br>
> -                         x1 := true]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true.<br>
> -         ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is runnable and none of the unwind blocks has finished yet"<br>
> -     self assert: p isRunnable.<br>
> -     self deny: x1 | x2 | x3 | x4.<br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateRunnableInNestedEnsure2 (in category 'tests') -----<br>
> - testTerminateRunnableInNestedEnsure2<br>
> -     "Terminate runnable process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -         [<br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [ ] ensure: [<br>
> -                         Processor yield. <br>
> -                         x1 := true]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true.<br>
> -         ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is runnable and none of the unwind blocks has finished yet"<br>
> -     self assert: p isRunnable.<br>
> -     self deny: x1 | x2 | x3 | x4.<br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateSuspendedInNestedEnsure1 (in category 'tests') -----<br>
> - testTerminateSuspendedInNestedEnsure1<br>
> -     "Terminate suspended process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -         [<br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [Processor activeProcess suspend] ensure: [<br>
> -                         x1 := true]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true.<br>
> -         ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> -     self assert: p isSuspended.<br>
> -     self deny: x1 | x2 | x3 | x4.<br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>
> Item was removed:<br>
> - ----- Method: UnwindTest>>testTerminateSuspendedInNestedEnsure2 (in category 'tests') -----<br>
> - testTerminateSuspendedInNestedEnsure2<br>
> -     "Terminate suspended process.<br>
> -     Test all nested unwind blocks are correctly executed; <br>
> -     all unwind blocks halfway through their execution should be completed."<br>
> - <br>
> -     | p x1 x2 x3 x4 |<br>
> -     x1 := x2 := x3 := x4 := false.<br>
> -     p := <br>
> -         [<br>
> -             [<br>
> -                 [ ] ensure: [<br>
> -                     [ ] ensure: [<br>
> -                         Processor activeProcess suspend. <br>
> -                         x1 := true]. <br>
> -                     x2 := true]<br>
> -             ] ensure: [<br>
> -                 x3 := true].<br>
> -             x4 := true.<br>
> -         ] newProcess.<br>
> -     p resume.<br>
> -     Processor yield.<br>
> -     "make sure p is suspended and none of the unwind blocks has finished yet"<br>
> -     self assert: p isSuspended.<br>
> -     self deny: x1 | x2 | x3 | x4.<br>
> -     "now terminate the process and make sure all unwind blocks have finished"<br>
> -     p terminate.<br>
> -     self assert: p isTerminated.<br>
> -     self assert: x1 & x2 & x3.<br>
> -     self deny: x4.!<br>
> <br>