> 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>
>